NSubstitute cannot determine argument specifications to use

Viewed 10002

I use NUnit and NSubstitute for unit testing. I have the following:

public interface IDataProvider
{
    void Log(int tvmId, DateTime time, int source, int level, int eventCode, string message);
}

...

var fakeDataProvider = Substitute.For<IDataProvider>();
...
fakeDataProvider.Received().Log(
    Arg.Any<int>(),
    new DateTime(2000, 1, 1),
    0,
    0,
    0,
    null);

fakeDataProvider.Received() throws AmbiguousArgumentException with the message that it cannot determine argument specifications to use. I have found the following on SO

Cannot determine argument specifications to use

which is related but I cannot apply it in the code above. Why is the above code ambiguous? How else could I specify to Received() that it should accept any argument?

3 Answers

Well, another trap for young players: if you have several calls to the same method in a single test, do not reuse argument specifiers across calls:

I have a virtual method that takes two Dictionary<string, MyStruct>:

var checkArg1 = Arg.Is<Dictionary<string, MyStruct>>(dico => dico.Count == 0);
var checkArg2 = Arg.Is<Dictionary<string, MyStruct>>(dico => dico.Count == 0);
mySubtitue.Received(1).myMethod(checkArg1, checkArg2);

// do something that triggers another call to MyMethod 
// ...

// second check using the same argument specifiers
mySubtitue.Received(1).myMethod(checkArg1, checkArg2);

You still get the "Please use specifications for all arguments of the same type".

Solution is to instantiate each time the arguments specifiers:

var checkArg1 = Arg.Is<Dictionary<string, MyStruct>>(dico => dico.Count == 0);
var checkArg2 = Arg.Is<Dictionary<string, MyStruct>>(dico => dico.Count == 0);
mySubtitue.Received(1).myMethod(checkArg1, checkArg2);

// do something that triggers another call to MyMethod 
// ...

// second check using new argument specifiers
checkArg1 = Arg.Is<Dictionary<string, MyStruct>>(dico => dico.Count == 0);
checkArg2 = Arg.Is<Dictionary<string, MyStruct>>(dico => dico.Count == 0);
mySubtitue.Received(1).myMethod(checkArg1, checkArg2);

You can use below code to do it

fakeDataProvider.Received().Log(
    Arg.Any<int>(),
    new DateTime(2000, 1, 1),
    Arg.Is(0),
    Arg.Is(0),
    Arg.Is(0),
    null);
Related