回答:
打ちにくいhttps://github.com/Moq/moq4/wiki/Quickstart
それが十分に明確でない場合は、それをドキュメントのバグと呼びます...
編集:あなたの説明に応じて...
Setup
実行するモックメソッドごとに、次のようなことを示すことができます。
この.Callback
メカニズムでは、「現在は説明できませんが、このような形の通話が発生したら、折り返し電話してください。必要な処理を行います」と書かれています。同じ流暢な呼び出しチェーンの一部として、返される結果(ある場合)を.Returns
" を介して制御できます。QSの例では、返される値が毎回増加する例がQSの例です。
一般に、このようなメカニズムはあまり必要ありません(xUnitテストパターンには、テスト中のilk条件付きロジックのアンチパターンの用語があります)。必要なものを確立するためのより簡単なまたは組み込みの方法がある場合は、優先的に使用されます。
Justin EtheredgeのMoqシリーズの4のパート3はそれをカバーし、ここにコールバックの別の例があります
コールバックの簡単な例は、Moqでのコールバックの使用に関する投稿にあります。
Callback
は戻り値とは何の関係もありません(コードを介してリンクする場合を除きます)。基本的に、コールバックが各呼び出しの前または後に呼び出されることを確認するだけです(それぞれ前または後のどちらにチェーンしたかによって異なりますReturns
)。
以下は、コールバックを使用して、挿入を処理するデータサービスに送信されたエンティティをテストする例です。
var mock = new Mock<IDataService>();
DataEntity insertedEntity = null;
mock.Setup(x => x.Insert(It.IsAny<DataEntity>())).Returns(1)
.Callback((DataEntity de) => insertedEntity = de);
代替のジェネリックメソッド構文:
mock.Setup(x => x.Insert(It.IsAny<DataEntity>())).Returns(1)
.Callback<DataEntity>(de => insertedEntity = de);
次に、次のようなものをテストできます
Assert.AreEqual("test", insertedEntity.Description, "Wrong Description");
It.Is<T>
in を使用する方がきれいな場合がありますMock.Verify
。しかし、+ 1は、例から最もうまくいく人がたくさんいると思うので。
Callback
Moqには2つのタイプがあります。1つは呼び出しが戻る前に発生します。もう1つは、呼び出しが戻った後に発生します。
var message = "";
mock.Setup(foo => foo.Execute(arg1: "ping", arg2: "pong"))
.Callback((x, y) =>
{
message = "Rally on!";
Console.WriteLine($"args before returns {x} {y}");
})
.Returns(message) // Rally on!
.Callback((x, y) =>
{
message = "Rally over!";
Console.WriteLine("arg after returns {x} {y}");
});
両方のコールバックで、次のことができます。
Callback
モックのメソッドの1つが呼び出されたときに、必要なカスタムコードを実行するための手段です。以下に簡単な例を示します。
public interface IFoo
{
int Bar(bool b);
}
var mock = new Mock<IFoo>();
mock.Setup(mc => mc.Bar(It.IsAny<bool>()))
.Callback<bool>(b => Console.WriteLine("Bar called with: " + b))
.Returns(42);
var ret = mock.Object.Bar(true);
Console.WriteLine("Result: " + ret);
// output:
// Bar called with: True
// Result: 42
最近、興味深いユースケースに遭遇しました。モックへのいくつかの呼び出しを期待しているが、それらは同時に発生するとします。したがって、それらが呼び出される順序を知る方法はありませんが、期待どおりの呼び出しが行われたことを(順序に関係なく)知りたいと考えています。あなたはこのようなことをすることができます:
var cq = new ConcurrentQueue<bool>();
mock.Setup(f => f.Bar(It.IsAny<bool>())).Callback<bool>(cq.Enqueue);
Parallel.Invoke(() => mock.Object.Bar(true), () => mock.Object.Bar(false));
Console.WriteLine("Invocations: " + String.Join(", ", cq));
// output:
// Invocations: True, False
ところで、誤解を招く「前Returns
」と「後Returns
」の区別によって混乱することはありません。これは、カスタムコードがReturns
評価された後または前に実行されるかどうかの技術的な違いにすぎません。呼び出し元の目には、値が返される前に両方が実行されます。実際、メソッドがvoid
-returningの場合、呼び出すこともできませんがReturns
、同じように機能します。詳細については、https://stackoverflow.com/a/28727099/67824を参照してください。