[英]Mock result from Func with NSubstitute
I'm trying to use NSubstitute to mock the return value from a Substitute, but I cannot get the substitute to return the correct value because the method signature is using a Func. 我正在尝试使用NSubstitute模拟Substitute的返回值,但是由于方法签名使用的是Func,因此我无法获得替代方法来返回正确的值。
I've seen these questions, but cannot make it work with my Func. 我已经看过这些问题,但是无法使其与Func一起使用。
Mocking Action<T> with NSubstitute 用NSubstitute模拟Action <T>
Mocking out expression with NSubstitute 用NSubstitute模拟表达
The interface I try to mock is this (somewhat simplyfied): 我尝试模拟的接口是这样的(有点简单):
public interface IOrgTreeRepository<out T> where T : IHierarchicalUnit
{
T FirstOrDefault(Func<T, bool> predicate);
}
I'm substituting it with NSubstitute like so: 我用NSubstitute替代它,如下所示:
_orgTreeRepository = Substitute.For<IOrgTreeRepository<IOrganizationUnit>>();
And then I try to change the return value like so: 然后尝试更改返回值,如下所示:
_orgTreeRepository.FirstOrDefault(Arg.Is<Func<IOrganizationUnit, bool>>(x => x.Id== _itemsToUpdate[0].Id)).Returns(existingItems[0]);
But it simply returns a proxy-object instead of my defined object in existingItems . 但是它只是返回一个proxy-object而不是我在existingItems中定义的对象。
However, thanks to the other questions I managed to get this to work, but it does not help me, since I need a specific item every time. 但是,由于其他问题,我设法使它起作用,但这对我没有帮助,因为我每次都需要特定的物品。
_orgTreeRepository.FirstOrDefault(Arg.Any<Func<IOrganizationUnit, bool>>()).Returns(existingItems[0]); // Semi-working
I guess it's treating the lambda expression as a kind of absolute reference and therefore skips it? 我猜它将lambda表达式视为一种绝对引用,因此跳过了它? Is there any way I can mock the return value?
有什么方法可以模拟返回值?
As you correctly guessed, NSubstitute just uses reference equality here, so unless you have a reference to the same predicate (which is sometimes an option) then you'll have to match any call ( Arg.Any
or .ReturnsForAnyArgs
) or use an approximate form of matching to check the function passed in. 正如您正确猜测的那样,NSubstitute仅在此处使用引用相等,因此,除非您有对相同谓词的引用(有时是一个选择),否则您必须匹配任何调用(
Arg.Any
或.ReturnsForAnyArgs
)或使用近似值匹配形式以检查传入的函数。
An example of approximate matching: 近似匹配的示例:
[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"));
}
Here we've stubbed FirstOrDefault
to return sample
whenever the Func<T,bool>
returns true
for sample
(this is using a different overload of Arg.Is
which takes an expression, rather than the value of the argument passed in). 这里我们存根
FirstOrDefault
返回sample
每当Func<T,bool>
返回true
对于sample
(这是使用的不同过载Arg.Is
它接受一个表达式,而不是传入的参数的值)。
This passes the test for two different predicates, because sample
satisfies both of them. 这通过了两个不同谓词的测试,因为
sample
满足了这两个条件。 It also passes the last assertion, in that it doesn't return sample
for a func that checks for a different id. 它还通过了最后一个断言,因为它不返回用于检查其他ID的func的
sample
。 We can't guarantee a specific predicate was used in this case, but it might be enough. 我们不能保证在这种情况下使用了特定的谓词,但这可能就足够了。 Otherwise we're stuck with reference quality on the Func.
否则,我们就无法保证Func的参考质量。
Hope this helps. 希望这可以帮助。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.