Nsubstitute: Returns doesn't work in 4.0.0

Created on 14 Feb 2019  路  4Comments  路  Source: nsubstitute/NSubstitute

Method Returns(value) doesn't work for boolean in version 4.0.0 when call has parameters. In version 3.1.0 works fine.

Version 4.0.0
This doesn't work - result is false:

var myRepository = Substitute.For<IMyRepository>();  
myRepository.EntityExists(Arg.Any<EntityFilter>()).Returns(true);  
var result = myRepository.EntityExists(Arg.Any<EntityFilter>());

This works - result is true:

var myRepository = Substitute.For<IMyRepository>();  
myRepository.EntityExists().Returns(true);  
var result = myRepository.EntityExists();

Version 3.1.0
In both cases (above) result is true.

For details, see attached solution.
NSubTest.zip

question

Most helpful comment

@zvirja Whenever I've seen this it has been with the intention of communicating to a reader that our result holds for any value of the argument type. For example, we could replace default(EntityFilter) with any EntityFilter and the test should still pass.

I definitely agree with using parameterised tests for this. Something like FsCheck (which is usable from C#) is perfect for expressing this idea. (Or Hedgehog, but I'm not sure that plays nicely with C#.)

All 4 comments

Hello!

There is a small issue with this code: arg matchers should only be used for asserting and stubbing calls.

For var result = myRepository.EntityExists(Arg.Any<EntityFilter>()), NSubstitute thinks you are stubbing the call and as of 4.0 will not run any other Returns logic to avoid running queued callbacks (see #347 for details). Instead, consider using something like:

var anyEntityFilter = default(EntityFilter); 
var result = myRepository.EntityExists(anyEntityFilter);

Hope this helps!

I would go even further and not use the misleading anyEntityFilter variable name, as false is very specific value. You cannot pass "any" argument to the method - you always pass concrete value. If you would like to test again the both variances, use InlineData attribute (for xUnit) and test both true and false.

@zvirja Whenever I've seen this it has been with the intention of communicating to a reader that our result holds for any value of the argument type. For example, we could replace default(EntityFilter) with any EntityFilter and the test should still pass.

I definitely agree with using parameterised tests for this. Something like FsCheck (which is usable from C#) is perfect for expressing this idea. (Or Hedgehog, but I'm not sure that plays nicely with C#.)

@p33nty Thank you for raising the ticket. I'm closing it. Feel free to reopen if the answer above didn't help.

Was this page helpful?
0 / 5 - 0 ratings