Moq.Langauge Callback Function

When doing this to project has Moq.4.16.1 and the namespace I used was Moq.Language but it was just resolved with using Moq;.

In the .Verify where you passed DynamicParameters its also possible to instead use It.Is<DynamicParameters>(x => x.Foo == "foo") but I wanted to try the callback option. There are some It.Is examples here.

Why Callback?

I was unit testing a command that runs a stored procedure for Dapper using DynamicParameters. The DynamicParameters are created privately inside the unit of work (the method Im testing).

The stack is MyController -> IMyCommand -> IDbUtility. For the purpose of this post I dont look at MyController, it only gives some context.

I needed to verify that foo and bar are set in the parameters in MyCommand.

1
2
3
4
5
6
7
8
9
10
11
public public class MyCommand : IMyCommand
{
public async Task RunProcAsync(string foo, string bar)
{
var parameters = new DynamicParameters();
parameters.Add("@foo", foo);
parameters.Add("@bar", bar);

_dbUtility.RunProc("MySweetProc", parameters);
}
}

As _dbUtility is injected into the constructor of my class under test, I was mocking it. So in the test I could use a .CallBack() to reach in and inspect the parameters.

Test Structure

After calling .Setup() to tell Moq which method and overload, I called .Callback. From the docs:

.Callback(…) Specifies a callback to invoke when the method is called that receives the original arguments

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// Arrange
var foo = "fooValue";
var bar = "barValue";
var dbUtilityMock = new Mock<IDbUtility>();
var capturedDynamicParameters = new DynamicParameters();

dbUtilityMock
.Setup(x => x.RunProc(procname, It.IsAny<DynamicParameters>()))
.Callback((string storedProcedureName, DynamicParameters parameters) =>
{
capturedDynamicParameters = parameters;
});

IMyCommand classUndertest = new MyCommand(databaseUtil.Object);

So then all I needed to do was call the unit of work and then check what was captured as capturedDynamicParameters

1
2
3
4
5
6
7
8
9
10
11
// Act
await classUndertest.RunProcAsync(foo, bar);

// Assert
_databaseUtil.Verify(x => x.RunProc(
"MySweetProc",
It.IsAny<DynamicParameters>()), Times.Once);

var parametersLookup = capturedDynamicParameters as SqlMapper.IParameterLookup;
Assert.Equal(parametersLookup["foo"], foo);
Assert.Equal(parametersLookup["bar"], bar);

I’ve used this .Callback() on the past for CancellationToken.

Easy!

References