我正在尝试使用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表达式视为一种绝对引用,因此会跳过它?有什么方法可以模拟返回值吗?
答案 0 :(得分:7)
正如您所猜测的那样,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>
时,我们都会true
发送sample
以返回Arg.Is
(这是{ {1}}接受表达式,而不是传入的参数的值)。
这传递了两个不同谓词的测试,因为sample
满足了它们。它还传递了最后一个断言,因为它不会为检查不同id的func返回sample
。我们无法保证在这种情况下使用特定的谓词,但它可能就足够了。否则,我们会在Func上坚持参考质量。
希望这有帮助。