2016-07-05 4 views
1

を使用して比較された受信通話を、上の主張は、次のサンプルをご覧ください:NSubstitute、引数がobject.ReferenceEquals

public interface IDomainClass 
    { 
     int A { get; set; } 
     void CalledMethod(IDomainClass data); 
    } 
    public class DomainClass : IDomainClass 
    { 
     public int A { get; set; } 

     public void CalledMethod(IDomainClass data) 
     { 
      throw new NotImplementedException(); 
     } 
    } 

そして、次のテスト:

[Test] 
    public void TestSample() 
    { 
     //Arrange 
     IDomainClass testingClass = Substitute.For<IDomainClass>(); 

     IDomainClass data = new DomainClass() { A = 123, }; 
     IDomainClass expectedResult = new DomainClass() { A = 123, }; 

     //Act 
     testingClass.CalledMethod(data); 

     //Assert 
     testingClass.ReceivedWithAnyArgs(1).CalledMethod(null); //ok 
     data.ShouldBeEquivalentTo(expectedResult);    //ok 
     testingClass.Received(1).CalledMethod(expectedResult); //fail 
    } 

問題は私です受信した呼び出し(CallMethod)の引数をテストする方法を知らない。つまり、最初のobject.ReferenceEquals、次にobject.Equalsを使用して引数を比較します。通常、メソッドに渡されるデータを制御できないため、オブジェクト(dataおよびexpectedResult)は同じオブジェクトを参照しません。

しかし、そこにそれを動作させるための方法である、と私は対等をオーバーライドする場合には、次のように:

 public override bool Equals(object obj) 
     { 
      return this.A.Equals((obj as DomainClass).A); 
     } 
     public override int GetHashCode() 
     { 
      return this.A.GetHashCode(); 
     } 

これは動作しますが、私はテストを満たすと等しいを実装する必要はありませんそれはここで言及する価値のない他のすべての意味を持っているからです。

は、私が欲しいのは同じ二アサートラインをやって比較演算子である:

data.ShouldBeEquivalentTo(expectedResult); 

しかし、これはデフォルトごとにサポートされていません。

この問題を解決するにはどうすればよいですか。 ありがとうございます。

答えて

1

NSubstituteはモーメント(V1.10)で、このために完全に焼きサポートしていません。 Issue 160にはこれに関するいくつかの議論があります。

David Osborneが挙げた1つの選択肢は、あなたのアサーションライブラリを使って引数をキャッチしてアサートすることです。

カスタム引数マッチャーを使用する方法もあります。コメントで述べたように、これは動作しますが、それが失敗したときに、かなりひどいエラーメッセージを提供するとの問題を抱えている、

[Test] 
public void UsingArgMatcher() { 
    var repos = Substitute.For<IRepos>(); 

    var sut = new SomeService(repos); 
    sut.Process(); 

    repos.Received().Save(Arg.Is(EquivalentTo(new int[] { 1, 2, 3 }))); 
} 

private Expression<Predicate<IEnumerable<T>>> EquivalentTo<T>(IEnumerable<T> enumerable) { 
    return x => Equiv(enumerable, x); 
} 

private bool Equiv<T>(IEnumerable<T> a, IEnumerable<T> b) { ... } 

:私はthis commentからの例を含めました。

hooking NSubstitute up to FluentAssertionsの例もあります。

+0

さて、私は同意します。エラーメッセージはきれいではありませんが、回避策があります。 –

0

あなたは渡されたものを保存し、後で比較することができます:

[Test] 
public void TestSample() 
{ 
    //Arrange 
    IDomainClass testingClass = Substitute.For<IDomainClass>(); 

    IDomainClass data = new DomainClass() { A = 123, }; 

    IDomainClass methodReceievedThis = null; 

    testingClass 
     .When(t => t.CalledMethod(Arg.Any<IDomainClass>()) 
     .Do(p => methodReceievedThis = p); 

    //Act 
    testingClass.CalledMethod(data); 

    //Assert 
    testingClass.ReceivedWithAnyArgs(1).CalledMethod(null); //ok 

    methodReceievedThis.ShouldBeEquivalentTo(data); 
} 
+0

それは本当ですが、CalledMethodが正確な引数を持った呼び出しを受け取ったかどうかはわかりません。 –

+0

'methodReceivedThis'は' CalledMethod() 'の呼び出しによってのみ設定できるので、テストのコンテキスト内で行います。 –

+0

もし私がすでに結果を知っていたら、私はそれをテストする必要はないでしょう:-)現実の世界では、別のメソッドを呼び出す方法、そのメソッドに配信するだろうと私はそれが私が受け取ることを期待するどのような引数をテストする理由です。 –

関連する問題