1

I am trying to mock a method with out parameter and call it for several times in unit test. Here is my main code:

foreach (Device device in deviceList)
{
   ResponseCode response = this.client.GetState(device.Name, out State state);
   DeviceStatus deviceStatus = new DeviceStatus
   {
      Device = device,
      ResponseCode = response,
      State = state
   }
}

Below is what I did in my test:

IClient mockClient;
var deviceList = new List<Device>
{
  new Device { Name = "device1" },
  new Device { Name = "device2" },
  new Device { Name = "device3" }
}
this.mockClient.GetState(Arg.Is<string>(x => x == "device1"), out State device1State).
    Returns(x =>
    {
      x[1] = preSetStateForDevice1;
      return ResponseCode.Success;
    });
this.mockClient.GetState(Arg.Is<string>(x => x == "device2"), out State device2State).
    Returns(x =>
    {
      x[1] = preSetStateForDevice2;
      return ResponseCode.Success;
    });
this.mockClient.GetState(Arg.Is<string>(x => x == "device3"), out State device3State).
    Returns(x =>
    {
      x[1] = preSetStateForDevice3;
      return ResponseCode.Success;
    });

In debug, I found that all three calls of GetState return the same result as the 1st call. I know there is posts for multiple returns without out parameter or single call for method with out parameter, but I cannot figure out how to make this multiple calls for method with out parameter works, please help. Thanks!

Update: I also tried to set out and return by call sequence not input value, like below:

this.mockClient.GetState(Arg.Any<string>(), out State state).
    Returns(x =>
    {
      x[1] = preSetStateForDevice1;
      return ResponseCode.Success;
    },
    x =>
    {
      x[1] = preSetStateForDevice2;
      return ResponseCode.Success;
    },
    x =>
    {
      x[1] = preSetStateForDevice3;
      return ResponseCode.Success;
    });

And it didn't work either

Update: Found a way from this post: NSubstitute, out Parameters and conditional Returns use ReturnsForAnyArgs instead of Returns in the 2nd try method will work. Don't know why though...

mxleon83
  • 11
  • 2

1 Answers1

0

Argument matching can be a bit tricky with out and ref parameters, as the value used when initially specifying the call will change during test execution.

The most reliable way to work around this is to use Arg.Any to match the out argument. For example:

mockClient
  .GetState(Arg.Is<string>(x => x == "device1"), out Arg.Any<State>())
  .Returns(...)

For more information on why this is an issue, see Setting out and ref arguments: Matching after assignments.

David Tchepak
  • 9,826
  • 2
  • 56
  • 68