使用N取代的Func模拟结果

本文关键字:模拟 结果 Func 取代 使用 | 更新日期: 2023-09-27 18:16:49

我试图使用NSubstitute来模拟Substitute的返回值,但我无法让Substitute返回正确的值,因为方法签名使用的是Func。

我看到了这些问题,但无法用我的Func解决。

模仿动作<T>用N取代

用N-取代模拟表达

我试图模拟的接口是这样的(有点简单(:

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

我用N取代它,就像这样:

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

使用N取代的Func模拟结果

正如您正确猜测的那样,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>sample返回true时,我们就将FirstOrDefault截断为返回sample(这是使用Arg.Is的另一个重载,它接受一个表达式,而不是传入的参数值(。

这通过了对两个不同谓词的测试,因为sample同时满足这两个谓词。它还传递了最后一个断言,因为它不会为检查不同id的函数返回sample。我们不能保证在这种情况下使用了特定的谓词,但这可能已经足够了。否则,我们将在Func上使用参考质量。

希望这能有所帮助。