web-dev-qa-db-ja.com

NSubstitute:配列引数を使用して受信したメソッドをチェックしています

NSubstituteモックのメソッドが特定の配列引数で呼び出されていることを確認したいのですが。

インターフェイスIProcessorにメソッドvoid ProcessSomething(Foo[] something])があるとします。テスト中のクラスの名前がCommanderだとします。私はこのように私のテストを設定しました:

_//prepare
var processor = Substitute.For<IProcessor>;
var commander = new Commander(processor);
var foo1 = new Foo("alpha");
var foo2 = new Foo("bravo");
var foos = new [] {foo1, foo2};

//act
commander.DoSomething(foo1, foo2);

//verify
processor.Received().ProcessSomething(foos);  // FAILS
_

Received()呼び出しは次のエラーで失敗します:

_NSubstitute.Exceptions.ReceivedCallsException : Expected to receive a call matching:
    ProcessSomething(Foo[])
Actually received no matching calls.
Received 1 non-matching call (non-matching arguments indicated with '*' characters):
    ProcessSomething(*Foo[]*)
_

これは、ProcessSomethingがfoos以外の配列で呼び出されたように見えますよね?

まあ、代わりにこれをテストする場合、Arg.Do()を使用して引数値をキャプチャすると、成功します。

_//prepare
//... as before
var actualFoos = null;

processor.ProcessSomething(Arg.Do<Foo[]>(x => actualFoos = x));

//act
commander.DoSomething(foo1, foo2);

//verify
Assert.That(actualFoos, Is.EqualTo(foos));   // SUCCEEDS
_

したがって、引数をキャプチャしてそれを(この例ではNUnitと)比較して機能しますが、受信した呼び出しの検証は失敗します。

これはNSubstituteのバグですか、それとも間違って使用していますか?

40
Jimothy

私は、あなたのCommanderオブジェクトが引数を取り、それらを配列に入れて、Processorモックを呼び出すために使用することを想定しています。

foos変数は、セットアップで作成する別の配列です。配列は、同じ要素があったとしても、互いに等しいとは見なされません。そのため、NSubstituteは期待値を受け取っていない(同じ要素を含む別の配列を受け取った)と文句を言います。

編集:このバージョンを試してください:

//prepare
var processor = Substitute.For<IProcessor>;
var commander = new Commander(processor);
var foo1 = new Foo("alpha");
var foo2 = new Foo("bravo");
var foos = new [] {foo1, foo2};

//act
commander.DoSomething(foo1, foo2);

//verify
processor.Received().ProcessSomething(Arg.Is<Foo[]>(foos2 => foos.SequenceEqual(foos2));

これには、System.Linq名前空間をインポートする必要があります

57
aKzenT