Two Ways to Count the Number of Times a Mocked Method is Called With Moq
Full source code available here.
When mocking a service you sometimes want to know how many times a method on that service was called, I had done this in the past and knew about Verify
. This class has some static methods that let you check this in a variety of ways.
Another option is to use the CallBack
method to increment a counter manually, then check that the counter has the expected value with an Assert
.
The method call to test
I have a very simple library with a FooService
that takes an IMathService
as a constructor parameter. The implementation of IMathService
doesn’t matter, what I want to check is the number of times the AddNumbers
method is called.
Using Verify
This is probably the best way to go as Verify
is designed for this exact purpose - to verify the number of times a method has been called.
Arrange - Inside the test method, mock the IMathService
(line 5), setup up the AddNumbers
method to return a known response to a specific invocation (line 6), create the FooService
passing it the mocked MathService
(line 8).
Act - Call the public method on the FooService
. This should in turn call the AddNumbers
method once on the mocked MathService
(line 11).
Assert - Finally assert that the AddNumbers
has been called once (line 15).
1[Fact]
2public void Check_Times_Called_With_Verify()
3{
4 // Arrange
5 Mock<IMathService> mathService = new Mock<IMathService>();
6 mathService.Setup(ms => ms.AddNumbers(1, 2)).Returns(3);
7
8 FooService fooService = new FooService(mathService.Object);
9
10 // Act
11 string result1 = fooService.AddMessageToAnswer("hello", 1, 2);
12
13 // Assert
14 Assert.Equal("hello 3", result1);
15 mathService.Verify(ms => ms.AddNumbers(1, 2), Times.Exactly(1));
16}
Using Callback
Another approach is to use the built-in Callback
that can execute on each method that is Setup
on a mocked service. Its syntax is simple, add the Callback
after the Return
. In this example, I use it to increment a counter (line 6).
The rest of the test is the same up to the Assert, where I check that counter has the expected value (line 16).
1[Fact]
2public void Check_Times_Called_With_Callback()
3{
4 // Arrange
5 int timesCalled = 0;
6 Mock<IMathService> mathService = new Mock<IMathService>();
7 mathService.Setup(ms => ms.AddNumbers(1, 2)).Returns(3).Callback(() => ++timesCalled);
8
9 FooService fooService = new FooService(mathService.Object);
10
11 // Act
12 string result = fooService.AddMessageToAnswer("hello", 1, 2);
13
14 // Assert
15 Assert.Equal("hello 3", result);
16 Assert.Equal(1, timesCalled);
17}
It.IsAny<>
Both approaches work with It.IsAny
for params to the mocked method, or when asserting with the Verify
. The attached zip file has examples of this.
Full source code available here.