NSubstitute - Check arguments passed to method
A bit late for the party, but ran into the same need. I am working with mockito in java, and they have an Argument capture helper that I like. It is basically the same as @Castrohenge answer
So here is my NSubstitute implementation.
public interface IFoo
{
void DoSomthing(string stringArg);
}
Argument capture class
public class ArgCapture<T>
{
private List<T> m_arguments = new List<T>();
public T capture()
{
T res = Arg.Is<T>(obj => add(obj)); // or use Arg.Compat.Is<T>(obj => add(obj)); for C#6 and lower
return res;
}
public int Count
{
get { return m_arguments.Count; }
}
public T this[int index]
{
get { return m_arguments[index]; }
}
public List<T> Values {
get { return new List<T>(m_arguments);}
}
private bool add(T obj)
{
m_arguments.Add(obj);
return true;
}
}
And the usage test case
[Test]
public void ArgCaptureTest()
{
IFoo foo1 = Substitute.For<IFoo>();
ArgCapture<string> stringArgCapture = new ArgCapture<string>();
foo1.DoSomthing("firstCall");
foo1.DoSomthing("secondCall");
foo1.Received(2).DoSomthing(stringArgCapture.capture());
Assert.AreEqual(2,stringArgCapture.Count);
Assert.AreEqual("firstCall",stringArgCapture[0]);
Assert.AreEqual("secondCall", stringArgCapture[1]);
}
I've figured out the answer myself.
NSubstitute just needs to use the .Received() call and then when you specify your argument to the method. You can specify the argument matching as a predicate.
For example:
helperMock.Received().ExecuteScalarProcedureAsync(Arg.Is<DatabaseParams>(
p => p.StoredProcName == "up_Do_Something"
&& p.Parameters[0].ParameterName == "Param1"
&& p.Parameters[0].Value.ToString() == "Param1Value"
&& p.Parameters[1].ParameterName == "Param2"
&& p.Parameters[1].Value.ToString() == "Param2Value"));
An alternative is to use Do
(see https://nsubstitute.github.io/help/actions-with-arguments/). I prefer this as it lets you call assertions against specific properties of the arguments, which gives you better feedback on which specific properties of the argument object are incorrect. For example:
StoredProc sp = null; // Guessing the type here
helperMock.Received().ExecuteScalarProcedureAsync(Arg.Do<DatabaseParams>(p => sp = p));
// NUnit assertions, but replace with whatever you want.
Assert.AreEqual("up_Do_Something", sp.StoredProcName);
Assert.AreEqual("Param1", p.Parameters[0].ParameterName);
Assert.AreEqual("Param1Value", p.Parameters[0].Value.ToString());
Assert.AreEqual("Param2", p.Parameters[1].ParameterName);
Assert.AreEqual("Param2Value", p.Parameters[1].Value.ToString());