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.
I've seen these questions, but cannot make it work with my Func.
Mocking Action<T> with NSubstitute
Mocking out expression with 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:
_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.
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? Is there any way I can mock the return value?
To set a return value for a method call on a substitute, call the method as normal, then follow it with a call to NSubstitute's Returns() extension method. var calculator = Substitute. For<ICalculator>(); calculator. Add(1, 2).
NSubstitute is a friendly substitute for . NET mocking libraries. It has a simple, succinct syntax to help developers write clearer tests. NSubstitute is designed for Arrange-Act-Assert (AAA) testing and with Test Driven Development (TDD) in mind.
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.
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).
This passes the test for two different predicates, because sample
satisfies both of them. It also passes the last assertion, in that it doesn't return sample
for a func that checks for a different id. 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.
Hope this helps.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With