C# – Moq callback with out parameter

ccallbackmoqoutunit testing

I'm trying to use Moq to mock a callback for the following method signature:

ResponseHeader AddIncentives(
        Hs_transRow[] data,
        out ResponseBody responseBody);

I want my callback to use the data which is passed in. However, I'm running into problems which I think are because the second parameter is an out parameter. I can setup and return data without problems, but the callback is an issue.

This is my current setup:

var addIncentiveResponseBody = new ResponseBody();

mockCoinsService
.Setup(service => service.AddIncentives(It.IsAny<Hs_transRow[]>(), out addIncentiveResponseBody))
.Callback((Hs_transRow[] data, ResponseBody body) =>
{
    //I want to use the data variable here
})
.Returns(() => new ResponseHeader
{
     action = ResponseHeaderAction.RESPONSE,
});

When I run this code as part of a unit test, I get the error:

Invalid callback. Setup on method with parameters (Hs_transRow[],ResponseBody&) cannot invoke callback with parameters (Hs_transRow[],ResponseBody).

I can see there is an ampersand difference, which I assume is because that parameter should be an out parameter. However, if I add the out keyword to the callback (and assign it a value within the callback), I get the build time error:

Delegate 'Action' does not take two arguments.

Is Moq unable to handle a callback for a method which has an out parameter, or am I doing something wrong?

[Edit] To clarify beyond any doubt, I am not asking how to set the value of the out parameter. This is already being done by the line:

var addIncentiveResponseBody = new ResponseBody();

Best Answer

This was pointed out in the comments by Jeroen Heier but adding it as an answer should make it more visible. Scott Wegner has written an OutCallback overload which can be used.

This is used as follows:

mockCoinsService
    .Setup(service => service.AddIncentives(It.IsAny<Hs_transRow[]>(), out 
    addIncentiveResponseBody))
    .OutCallback((Hs_transRow[] data, ResponseBody body) =>
    {
        //I can now use the data variable here
    })
    .Returns(() => new ResponseHeader
    {
         action = ResponseHeaderAction.RESPONSE,
    });
Related Topic