编程语言
首页 > 编程语言> > c# – 来自Func和NSubstitute的模拟结果

c# – 来自Func和NSubstitute的模拟结果

作者:互联网

我正在尝试使用NSubstitute来模拟替换的返回值,但我无法让替换返回正确的值,因为方法签名使用的是Func.

我已经看过这些问题了,但是不能让它与我的Func一起工作.

Mocking Action<T> with NSubstitute

Mocking out expression with NSubstitute

我试图模拟的界面是这样(有点简单):

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

我用NSubstitute代替它:

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

然后我尝试更改返回值,如下所示:

_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表达式视为一种绝对引用,因此会跳过它?有什么方法可以嘲笑返回值吗?

解决方法:

正如你正确猜到的那样,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"));
}

每当Func< T,bool>时,我们都会使用FirstOrDefault来返回样本.对于样本返回true(这是使用不同的Arg.Is重载,它接受一个表达式,而不是传入的参数的值).

这通过了两个不同谓词的测试,因为样本满足了它们.它还传递了最后一个断言,因为它不会为检查不同id的func返回样本.我们不能保证在这种情况下使用特定的谓词,但它可能就足够了.否则我们会坚持使用Func上的参考质量.

希望这可以帮助.

标签:c,unit-testing,nsubstitute
来源: https://codeday.me/bug/20190611/1221455.html