I am new to Moq and I am trying to implement 2 tests that check for a HttpStatusCode.NotModified and HttpStatusCode.Ok. However, the latter passes its test, but the former doesn't and returns the exception:
Moq.MockException : Expected invocation on the mock once, but was 0 times: x => x.UpdateStateAsync(It.Is(y => y == RedisServiceModel))
Here is the HttpStatusCode.Ok which passes:
[Fact]
public void UpdateState_StateHasBeenUpdated_HttpOk()
{
//arrange
var state = new RedisServiceModel();
var redisServiceMock = new Mock<IRedisService>();
redisServiceMock.Setup(x => x.UpdateStateAsync(It.Is<RedisServiceModel>(y => y == state))).ReturnsAsync(state);
var testController = new TestController(redisServiceMock.Object);
// act
var statusResult = testController.UpdateStates(state);
// assert
redisServiceMock.Verify(x => x.UpdateStateAsync(It.Is<RedisServiceModel>(y => y == state)));
Assert.True(statusResult.Result is HttpStatusCode.OK);
}
Here is the HttpStatusCode.NotModified which throws the exception:
[Fact]
public void UpdateState_StateHasNotBeenModified_HttpNotModified()
{
//arrange
var state = new RedisServiceModel();
var redisServiceMock = new Mock<IRedisService>();
redisServiceMock.Setup(x => x.UpdateStateAsync(It.Is<RedisServiceModel>(y => y == state))).ReturnsAsync(state);
var testController = new TestController(redisServiceMock.Object);
// act
var statusResult = testController.UpdateStates(null);
// assert
redisServiceMock.Verify(x => x.UpdateStateAsync(It.Is<RedisServiceModel>(y => y == state)), Times.Once);
Assert.True(statusResult.Result is HttpStatusCode.NotModified);
}
Here is the PUT api call:
[HttpPut]
[Route("updatestates")]
public async Task<HttpStatusCode> UpdateStates(RedisServiceModel update)
{
RedisServiceModel updateState = await _redisService.UpdateStateAsync(update);
if (updateState != null)
{
return HttpStatusCode.OK;
}
return HttpStatusCode.NotModified;
}
I'm guessing it's because I'm passing in null here testController.UpdateStates(null). I did try wrapping everything in the UpdateStates API method to null check the update argument, but this still yielded the same exception. If anymore code is needed let me know and I'll edit this post.
The subject should be awaited, otherwise the assertion could be made before the subject has completed the expected behavior
The mock should also be configured to return the passed argument to mimic the expected behavior of the actual implementation
[Fact]
public async Task UpdateState_StateHasNotBeenModified_HttpNotModified() {
//arrange
var state = new RedisServiceModel();
var redisServiceMock = new Mock<IRedisService>();
redisServiceMock
.Setup(x => x.UpdateStateAsync(It.IsAny<RedisServiceModel>()))
.ReturnsAsync(x => x);
var testController = new TestController(redisServiceMock.Object);
// act
var statusResult = await testController.UpdateStates(null);
// assert
redisServiceMock.Verify(x => x.UpdateStateAsync(
It.Is<RedisServiceModel>(y => y == null)),
Times.Once);
Assert.True(statusResult is HttpStatusCode.NotModified);
}
The same should also have been done for the other test
[Fact]
public async Task UpdateState_StateHasBeenUpdated_HttpOk()
{
//arrange
var state = new RedisServiceModel();
var redisServiceMock = new Mock<IRedisService>();
redisServiceMock
.Setup(x => x.UpdateStateAsync(It.Is<RedisServiceModel>()))
.ReturnsAsync(x => x);
var testController = new TestController(redisServiceMock.Object);
// act
var statusResult = await testController.UpdateStates(state);
// assert
redisServiceMock.Verify(x => x.UpdateStateAsync(
It.Is<RedisServiceModel>(y => y == state)));
Assert.True(statusResult is HttpStatusCode.OK);
}
That said, the subject action should be refactored to follow proper syntax for controllers.
Assuming the controller is derived from ControllerBase it would have access to helper methods for action results.
[HttpPut]
[Route("updatestates")]
public async Task<IActionResult> UpdateStates(RedisServiceModel update) {
RedisServiceModel updateState = await _redisService.UpdateStateAsync(update);
if (updateState != null) {
return Ok();
}
return StausCode((int)HttpStatusCode.NotModified);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With