2015-10-08 36 views
3

我試圖用NSubstitute來模擬替代品的返回值,但我無法獲得替代品以返回正確的值,因爲方法簽名使用的是Func。Func與NSubstitute的模擬結果

我見過這些問題,但無法使它與我的Func一起工作。

Mocking Action<T> with NSubstitute

Mocking out expression with NSubstitute

我試圖嘲弄的接口是這個(有點simplyfied):

public interface IOrgTreeRepository<out T> where T : IHierarchicalUnit 
{ 
    T FirstOrDefault(Func<T, bool> predicate); 
} 

我與NSubstitute取代它像這樣:

_orgTreeRepository = Substitute.For<IOrgTreeRepository<IOrganizationUnit>>(); 

然後我嘗試改變返回v區實習像這樣:

_orgTreeRepository.FirstOrDefault(Arg.Is<Func<IOrganizationUnit, bool>>(x => x.Id== _itemsToUpdate[0].Id)).Returns(existingItems[0]); 

但它只是返回一個代理對象,而不是在existingItems我定義的對象。

但是,由於其他問題,我設法使這個工作,但它並沒有幫助我,因爲我每次都需要一個特定的項目。

_orgTreeRepository.FirstOrDefault(Arg.Any<Func<IOrganizationUnit, bool>>()).Returns(existingItems[0]); // Semi-working 

我想這是治療lambda表達式作爲一種絕對參考,因此跳過它?有什麼辦法可以嘲笑返回值嗎?

回答

4

正如你猜中,NSubstitute只是使用引用相等在這裏,所以除非你有相同的謂詞(有時是一個選項)的引用,那麼你就必須匹配任何呼叫(Arg.Any.ReturnsForAnyArgs)或使用匹配的近似形式檢查功能通過

近似匹配的例子:

[Test] 
public void Foo() { 
    var sample = new Record("abc"); 
    var sub = Substitute.For<IOrgTreeRepository<Record>>(); 
    sub.FirstOrDefault(Arg.Is<Func<Record,bool>>(f => f(sample))).Returns(sample); 

    Assert.AreSame(sample, sub.FirstOrDefault(x => x.Id.StartsWith ("a"))); 
    Assert.AreSame(sample, sub.FirstOrDefault(x => x.Id == "abc")); 
    Assert.Null(sub.FirstOrDefault(x => x.Id == "def")); 
} 

這裏我們存根FirstOrDefault返回sample每當Func<T,bool>回報truesample(這是使用Arg.Is的不同超載,它接受一個表達式,而不是傳入的參數的值)。

由於sample滿足這兩個謂詞,因此它通過了兩個不同謂詞的測試。它也傳遞最後一個斷言,因爲它不返回sample作爲檢查不同ID的func。我們無法保證在這種情況下使用了特定的謂詞,但它可能已足夠。否則,我們堅持在Func上提供參考質量。

希望這會有所幫助。

+0

那麼,這是一個很好的解決我的問題。非常感謝。 – smoksnes

+0

我從來沒有猜到過!萬分感謝。 – Invvard