質問
だから私は次のクラスを持っています:
public class MyClass {
internal void A() {
foreach(Thing thing in ThingArray)
B(thing);
}
virtual internal void B(Thing thing)
{
// do some stuff
}
}
そして、次のテストがあります:
...
var testObject = new Mock<MyClass>(parameters);
testObject.Setup(t => t.B(It.IsAny<Thing>()));
test.Object.A();
test.Verify(t => t.B(It.IsAny<Thing>()), Times.Exactly(2));
そして検証は失敗しています。確認しましたが、コードはモックされたB()メソッドではなく real B()メソッドを呼び出しています。
Moqが完璧に機能する場所で多くのコードを実行し、ここで何か間違ったことをしなければならないことを理解するのに十分な長さのコーディングを行ってきましたが、私の人生ではそれを見ることができません。私はtest。 Object .A()を呼び出しているので、B()の呼び出しはモックを通過しないという仮定の下で進めてきましたが、実際には何もしません他のオブジェクトからの呼び出しも同じように機能するので、私には感覚があります...
では、いったいなぜ、モックされたセットアップが実行されないのですか?
編集:はい、テストプロジェクトから内部を見ることができます。誰かがそれに言及することを知っていたので、私はそれを元の投稿に入れるつもりでした。
実際のコードについては、残念ながら非常に独自のものであるため、投稿することはできません。明日、コードを調整して実際にコンパイルできるかどうかを確認します。
解決
Gamlorの答えが機能するかどうかはわかりません。 Class1.MethodAがClass1.MethodBを呼び出すことを確認するメソッドでセットアップを実行する場合は、(InternalsVisibleToに関係なく)MethodB(セットアップを行うもの)をパブリックにする必要があります。同様の状況で簡単なテストを作成し、MethodBを公開するとMoqが動作し始めたことがわかりました。メソッドBを公開した場合、きっと動作するでしょう。
これはCastleまたはMoqのバグだと思いますが、確かではありません。誰かがチャイムを鳴らすことを願っています。
MethodBをパブリックにするのは良い選択ではないことを知っています。しかし、それは私が状況について知っていることです...
他のヒント
メソッドを正常にモックにするために、モックがこの基準を満たす必要があるオブジェクト:
- インターフェースでなければなりません
- または、モックするメソッドは仮想メソッドであり、パブリックである必要があります。
今では、仮想内部メソッドをモックすることもできますが、それを可能にするには、内部へのMoqアクセスを許可する必要があります。これは次の方法で実行できます。
[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")]
これにより、Moqのコードジェネレーターが内部にアクセスできるようになります。
したがって、 MyClass.A
呼び出しをモックするには、これを行う必要があります。
- メソッドAをバーチャルにします。
-
メソッドを公開するか、アクセスを許可します
<*>
または前述のように、MyClassのAPIを表すインターフェイスを作成します。
Moqは既存のコードをラップしませんが、代わりに空のモックを作成します。
つまり、testObject.Object.A()を呼び出しても元のコードは実行されないため、Bは呼び出されません。
インターフェースをモックするふりをする場合、インターフェースにはコードがなく、モックも同様なので、これは理にかなっています。
次のようにモックを作成してみてください(試していないので、動作するかどうかわかりません):
var testObject= new Mock<MyClass> { CallBase = true };