2016-07-05 24 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)從不會引用同一個對象。

然而,有一種方法,使其工作,那就是如果我重載Equals,像這樣:

 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沒有在時刻(1.10版)這個完全出爐的支持。 Issue 160對此有一些討論。

大衛奧斯本提到的一個選擇是捕捉參數並使用您選擇的斷言庫進行斷言。

另一種是使用自定義參數匹配器。我已經包括了一個例子,從this comment

[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) { ... } 

正如評論所述,這工作,但有失敗時提供了一個非常可怕的錯誤消息的問題。

還有一個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

如果我已經知道了結果,那麼我就不必去測試它了,對:-)很明顯,在現實世界中,我不知道什麼是方法 - 即調用另一種方法,也許調用另一種方法 - 將交付給該方法,這就是爲什麼我測試我期望它接收什麼參數。 –