29

私は Moq を使用しており、ビルダー クラスを作成して、必要に応じてテスト セットアップ中にオーバーライドできる事前設定された合理的なデフォルトでモックを作成したいと考えています。私が採用したアプローチでは、入力パラメーター値と期待される出力を渡す拡張メソッドを使用します。そうすることで、意味的に同等のコードと思われるものに異なる動作が見られます.It.IsAny()をセットアップで直接渡すのと、It.IsAny()の値をセットアップで間接的に渡す. 例:

public interface IFoo
{
    bool Bar(int value);
    bool Bar2(int value);
}
public class Foo : IFoo
{
    public bool Bar(int value) { return false; }
    public bool Bar2(int value) { return false; }
}

var mock = new Mock<IFoo>();
mock.Setup(x => x.Bar(It.IsAny<int>())).Returns(true);
Assert.IsTrue(mock.Object.Bar(123));                    // Succeeds

var myValue = It.IsAny<int>();
mock.Setup(x => x.Bar2(myValue)).Returns(true);
Assert.IsTrue(mock.Object.Bar2(123));                   // Fails

両方の呼び出しは (私にとっては) 同等ですが、Bar2 への呼び出しはアサーションに失敗します。どうしてこれなの?

4

2 に答える 2

43

It.IsAnyコンストラクト内で使用された場合にのみ、Moq がメソッド呼び出しの将来の呼び出しに一致することを許可しますSetup。がSetup呼び出されると、Moq はメソッド呼び出しをセットアップ済みのメソッド呼び出しのキャッシュに追加するだけです。例の引数 toSetupには type があることに注意してくださいExpression<Func<IFoo, bool>>。を渡しているためExpression、実際のメソッド呼び出しは呼び出されず、Moq には式をトラバースして、メソッド呼び出しのどのパラメーターが明示的で、どのパラメーターがIt.IsAny引数であるかを判断する機能があります。この機能を使用して、実行時の将来のメソッド呼び出しが、既に設定されているメソッド呼び出しの 1 つと一致するかどうかを判断します。

メソッドBarが引数 を受け取れるようにするためには、 return を anIt.IsAny<int>()にする必要があります ( の引数の型なので)。一般に、 の戻り値の型は でなければなりません。の任意の値を選択する必要があります。最も自然な選択は、参照型と値型で機能する です。(デフォルト キーワードの詳細については、こちらを参照してください)。あなたの場合、それは です。 It.IsAny<int>()intBarIt.IsAny<T>TTdefault(T)default(int)0

したがって、実際に評価It.IsAny<int>()すると の値0がすぐに返されます。ただし、(メソッドへの引数のように) で使用It.IsAny<int>()すると、メソッド呼び出しのツリー構造が保持され、Moq は将来のメソッド呼び出しを でカプセル化されたメソッド呼び出しに一致させることができます。 ExpressionSetupExpression

It.IsAny<int>()したがって、意味のある方法で変数として保持することはできませんがExpression、変数全体を保持することはできます。

Expression<Func<IFoo, bool>> myExpr = x => x.Bar2(It.IsAny<int>());
mock.Setup(myExpr).Returns(true);
Assert.IsTrue(mock.Object.Bar2(123));  

最後に、Moq はオープン ソースであることを思い出してください。ソースはこちらから入手できます。そのソース コードがあれば、クリックしてコードや単体テストを調べることができるので、とても便利です。

于 2013-06-12T03:04:06.323 に答える
1

It.IsAny<int>()戻り値の型が int で return0であるため、2 番目のセットアップは次のようになります。

mock.Setup(x => x.Bar2(0)).Returns(true);

私は moq コードをチェックしませんでしたが、setup メソッドで式を評価するときに、パラメーターが実際には It.IsAny 対通常の数値であることを考慮していることは確かです。

ヘルパー メソッドで直接セットアップを作成し、It.IsAny を渡さない方がよいでしょう。

于 2013-06-11T21:06:12.947 に答える