Moq (It.isAny & mock multiple calls)
Mocking examples with Moq
It.IsAny<T> variables
Those are argument matchers we have in Moq for the case we don’t have the same instance match.
Exact instance match - most restrictive
Example for default comparison
[Theory, Autodata]
public async Task FilledString_Execute_CorrectlyProcessed(string name, AnimalDTO animal)
{
// ARRANGE
_dependencyMock
.Setup(m => m.Load(name))
.Returns(animal)
// ACT
AnimalDTO result = await _sut.Execute(name);
// ASSERT
_dependencyMock.Verify(m => m.Load(name));
}
It.IsAny<T> - most permissive
Matches any instance of that type, null included.
[Theory, Autodata]
public async Task FilledString_Execute_CorrectlyProcessed(string name, AnimalDTO animal)
{
// ARRANGE
_dependencyMock
.Setup(m => m.Load(name))
.Returns(animal)
// ACT
AnimalDTO result = await _sut.Execute(name);
// ASSERT
// we use this in case the property is not accesible
// for example: a param created inside the class
_dependencyMock.Verify(m => m.Load(It.IsAny<string>()));
}
It.Is<T>(predicate)
Matches only when the predicate is true.
[Theory, Autodata]
public async Task FilledString_Execute_CorrectlyProcessed(string name, AnimalDTO animal)
{
// ARRANGE
_dependencyMock
.Setup(m => m.Load(name))
.Returns(animal)
// ACT
AnimalDTO result = await _sut.Execute(name);
// ASSERT
_dependencyMock.Verify(m => m.Load(It.Is<AnimalDTO>(a => a.Name == name)));
}
It.IsNotNull<T>
Only checks something is not null
[Theory, Autodata]
public async Task FilledString_Execute_CorrectlyProcessed(string name, AnimalDTO animal)
{
// ARRANGE
_dependencyMock
.Setup(m => m.Load(name))
.Returns(animal)
// ACT
AnimalDTO result = await _sut.Execute(name);
// ASSERT
_dependencyMock.Verify(m => m.Load(It.IsNotNull<AnimalDTO>()));
}
Mock multiple calls with same params
This is an example on how to mock a call when it’s called multiple times, and with the same parameter type every time.
Setup
I have the following class…
public class ConnectorRequest
{
public string Query { get; set; }
}
… which will be consumed by the following service
public class IConnectorService
{
Task<string> Execute(ConnectorRequest request);
}
Then I have a class which calls IConnectorService multiple times
public class ConnectorConsumerService
{
private IConnectorService _service;
// ...
public async Task<string> Process()
{
// ... does whatever
var response1 = await _service.Execute(request1);
// ... does whatever with that information
var response2 = await _service.Execute(request2);
// ... does whatever with that information
var response3 = await _service.Execute(request3);
// ... does whatever with that information
// ... does whatever else
}
// ...
}
Test
Test which mocks multiple calls
public class ConnectorConsumerServiceTest
{
// all mocks and stubs
private Mock<IConnectorService> _dependencyMock;
// service under test
private ConnectorConsumerService _service;
public ConnectorConsumerServiceTest()
{
_dependencyMock = new Mock<IConnectorService>();
_service = new ConnectorConsumerService(_dependencyMock.Object);
}
[Fact]
public async Task ProcessXXX_CaseXXX_ShouldReturnOkay()
{
// ARRANGE
// example starts here! ->
var responseToExecution1 = new ConnectorRequest
{
Query = "some response";
}
var responseToExecution2 = new ConnectorRequest
{
Query = "another response";
}
var responseToExecution3 = new ConnectorRequest
{
Query = "oh no! a response";
}
_dependencyMock.SetupSequence(mock => mock.Execute(It.IsAny<ConnectorRequest>()))
.ReturnsAsync(responseToExecution1)
.ReturnsAsync(responseToExecution2)
.ReturnsAsync(responseToExecution3);
// <- example ends here
// ACT
var result = await _service.Process();
// ASSERT
result.status.Should().NotBeNull();
// ... assert whatever
}
}