Search code examples
c#unit-testingtestingmockingnsubstitute

Capture multiple arguments with NSubstitute


I am using NSubstitute to write a unit test, and am trying to capture multiple method arguments passed in a method call.

I understand that I can capture a single argument using the Arg.Do<T>() matcher by doing something like this for SomeMethod which only accepts one parameter:

TArg? receivedArg = null;
SomeClass.SomeMethod(Arg.Do<TArg>(arg => receivedArg = arg));

However in my case, SomeMethod multiple arguments, and I want to capture all of them in each call.


Solution

  • Check the Callbacks, void calls and When..Do topic.

    You can hook an Action<CallInfo> callback to your SomeMethod method; its CallInfo argument has an Args method that returns all passed arguments as an object[] array. There's also an ArgAt<T>(int position) method for strong typed access to a specific argument.


    object[] receivedArgs;
    int receivedArg1;
    string receivedArg2;
    bool receivedArg3;
    
    var dependency = Substitute.For<IDependency>();
    
    dependency
        .When(o => o.SomeMethod(Arg.Any<int>(), Arg.Any<string>(), Arg.Any<bool>()))
        .Do(callInfo =>
        {
            receivedArgs = callInfo.Args();
    
            receivedArg1 = callInfo.ArgAt<int>(0);
            receivedArg2 = callInfo.ArgAt<string>(1);
            receivedArg3 = callInfo.ArgAt<bool>(2);
        });
    
    var myClass = new MyClass(dependency);
    myClass.Run();
    
    // Check received args here.
    
    public interface IDependency
    {
        void SomeMethod(int arg1, string arg2, bool arg3);
    }
    
    public class MyClass
    {
        private readonly IDependency _dependency;
    
        public MyClass(IDependency myClass)
        {
            _dependency = myClass;
        }
    
        public void Run()
        {
            _dependency.SomeMethod(123, "foo", false);
        }
    }