NSubstitute
NSubstitute copied to clipboard
Received only one call with only a specific parameter.
Hello, thank you for your help.
In my code I encounter the following scenario extremely often:
obj.Received(1).SampleMethod("sample");
obj.Received(1).SampleMethod(Arg.Any<string>());
It is testing whether I received a single call to a specific method, only with a certain parameter value. Using these two lines allows me to test that. The first line assures that this method was called with a specific parameter, and the second line assures that this method was called only once. I don't use obj.ReceivedCalls().Count() == 1, because I want to allow other methods to be called any amount of times, but one specific method should have been called a single time with a specific parameter.
I encountered this situation extremely often in my code. Almost every second test or so. And there are always these 2 lines there that are kind of one thing. Is there a clean way do this in a single command?
Hi @DasOhmoff ,
We haven't implemented anything for this scenario (there is some discussion of strict checking in https://github.com/nsubstitute/NSubstitute/issues/219 that has some links to potential options).
Would it be sufficient to add a static method to your project for this? Easiest way would probably be something like this (untested code!):
public static void ReceivedOnly<T>(this T sub, Action<T> call) {
call(sub.Received(1));
call(sub.ReceivedWithAnyArgs(1));
}
A more comprehensive way to do this would probably be via the query model used for Received.InOrder. I believe this could be used to implement strict checking of calls.
Well, it is not very clean.
- If the method I want to check has parameters I will need many overloads for all these parameters,
- also I will need many more method overloads depending whether this function has a return type or not
- also the implementation is not very clean:
SampleClass obj = new SampleClass();
obj.ReceivedOnly(SampleClass.TestMethod, "sampleString", 0, 1.0f); // <--- with parameters
It would be a lot nicer if something like the following was possible:
SampleClass obj = new SampleClass();
obj.ReceivedOnly().TestMethod("sampleString", 0, 1.0f);
A more comprehensive way to do this would probably be via the query model used for Received.InOrder. I believe this could be used to implement strict checking of calls.
Sorry, what do you mean by that? Could you please give me an example?
Ups sorry, closed this by accident.
I think ReceivedOnly call would look more like this?
obj.ReceivedOnly(sub => sub.TestMethod("sampleString", 0, 1.0f));
An example of the query model is this code: https://github.com/nsubstitute/NSubstitute/blob/master/src/NSubstitute/Received.cs
The assertion used there is: https://github.com/nsubstitute/NSubstitute/blob/master/src/NSubstitute/Core/SequenceChecking/SequenceInOrderAssertion.cs
Ah true, I got confused by my own solution that I built. But now thinking about it, the code you wrote seems to call the TestMethod multiple times.
Anyway, I still think obj.ReceivedOnly().TestMethod("sampleString", 0, 1.0f); would be the most elegant and suiting solution for NSubstitute.
Is there a reason not to implement it?
Anyway, I still think obj.ReceivedOnly().TestMethod("sampleString", 0, 1.0f); would be the most elegant and suiting solution for NSubstitute. Is there a reason not to implement it?
We already feel pretty guilty about bloating intellisense with extensions on Object, so we'd like to avoid this. NSubstitute was designed for non-strict mocking, so for the standard approach to using substitutes ReceivedOnly would be an edge case, but would add an intellisense entry to every .NET value. I think this may be better suited to a project-specific implementation, or an NSubstitute.Community.* package with an implementation similar to the one in this thread.
the code you wrote seems to call the TestMethod multiple times.
Yes, but the substitute will be in "assert received" mode at that time so the TestMethod call won't be recorded.