0

Expression<Func<Entity, bool>>次のように、式 ( ) を使用して結果をフィルター処理する、リポジトリとやり取りするコードの単体テストを行っています。

int orderId = 10;

_respository.GetFiltered(order => order.Id == orderId);

単体テストで問題が発生しています。具体的には、式が一致するという期待を設定しています。単体テストでは、これを行いたい:

_mockRespository.Setup(r => r.GetFiltered(order => order.Id == 10)).Returns(new Order[0]).AtMostOnce();

各式で実行して比較することを提案する 1 つの解決策を見つけまし.ToString()たが、orderId などの変数を参照すると、式がまったく異なります。

これをテストするために人々は何をしていますか?

ありがとう、

デビッド

4

1 に答える 1

0

これは、単体テストで実際に何を検証したいかという問題の一部であり、単体テストの哲学に帰着します。

私たちがしていることは、タイプ A (テスト中) から渡された linq to entities 式パラメーターが、リポジトリ コラボレーター (テスト中ではない) で GetFoo() を呼び出すときに特定の式ツリーを使用することを必ずしも検証しないことです。単体テストでは、メソッド GetFoo() が正しい署名を呼び出していることを確認できれば満足です。

あなたの場合、Moq (?) を使用しているように見えますが、その場合は次のようになります (構文の混乱に注意してください)。

_mockRespository.Setup(r => r.GetFiltered(It.IsAny<Expression<Func<Entity, bool>>>())).Returns(new Order[0]).AtMostOnce();

私たちにとって、これは理にかなっています。なぜなら、a) モックされたメソッドのパラメーター式ツリーの比較検証は確かに苦痛であり、b) そのパラメーターを検証できたとしても、B がパラメーター値のさまざまな組み合わせを実際に解釈する方法が変わる可能性があるからです (コントラクト A のセマンティクスのように) ->B) その場合、テストが脆弱になります。

プロダクション A とプロダクション B の間の相互作用をテストするために、自動化されたストーリー テストを使用します。これらのシナリオをテストするには、これがより良い方法であると考えています。マッチ'。私たちにとって、これは統合テストとして理にかなっています (通常、1 つまたは 2 つの幸せなケースで十分です)。

それだけでは不十分な場合は、a) カスタム Moq マッチャーを作成する方法を読んでください。パラメータをキャプチャして、テスト後に調べることができます。このようなもの:

    Expression<Func<Entity, bool>> actualExpression = null;
    _mockRespository.Setup(r => r.GetFiltered(It.IsAny<Expression<Func<Entity, bool>>>())).Returns(new Order[0]).AtMostOnce().Callback((Expression<Func<Entity, bool>> expr => { actualExpression = expr});

    // exercise production code

    Assert.IsTrue(actualExpression ...... someithing clever here);

注: 上記のコードはすべて、スタック オーバーフロー エディターで記述されています。コンパイルされない場合、私に責任を負わせないでください。これについては Moq のドキュメントで説明されています

于 2011-08-18T15:14:18.020 に答える