2015-10-08 37 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