Frameworks
.NETCoreApp 1.1
EF Core 1.1.1
Xunit 2.2.0
Moq 4.7.8
Controller Post Method
_yourRepository
is injected in the controllers constructor and is of type IYourRepository
[HttpPost(Name = "CreateMethod")]
public async Task<IActionResult> CreateMethod([FromBody] ObjectForCreationDto objectDto)
{
if (objectDto== null)
{
return BadRequest();
}
if (!ModelState.IsValid)
{
return BadRequest();
}
await _yourRespository.CreateObject(objectDto);
if (!await _yourRespository.Save())
{
throw new Exception("Creating this object failed on save.");
}
return Ok();
}
Unit Test that fails
[Fact]
public async Task CreateObject_WhenGoodDtoReceived_SuccessStatusReturned()
{
// Arrange
var mockRepo = new Mock<IYourRepository>();
var controller = new YourController(mockRepo.Object);
var objectForCreationDto = new ObjectForCreationDto { Code = "0001", Name = "Object One" };
// Act
var result = await controller.CreateObject(objectForCreationDto);
// Assert
Assert.IsType<OkObjectResult>(result);
}
The test fails because the line
if (!await _yourRespository.Save())
Always evaluates to true. When it evaluates to true you can see that the code throws an error (which is handled by middleware)
_yourRepository.Save() method
public async Task<bool> Save()
{
return (await _yourContext.SaveChangesAsync() >= 0);
}
I'm not sure how to solve the problem and I'm not 100% sure why it is failing.
Is it because the mocked IYourRepository
interface doesn't include an implementation of the Save
method?
If so, does that mean to test the Post
method I would need to mock my DbContext and construct my YourRepository
object using it?
Any explanation as to why this is failing and how to rectify it would be much appreciated
You need to setup the repo to return a proper task from the async method. Moq allows this using ReturnsAsync
[Fact]
public async Task CreateObject_WhenGoodDtoReceived_SuccessStatusReturned()
{
// Arrange
var mockRepo = new Mock<IYourRepository>();
mockRepo.Setup(_ => _.Save()).ReturnsAsync(true);//<-- ADD THIS
var controller = new YourController(mockRepo.Object);
var objectForCreationDto = new ObjectForCreationDto { Code = "0001", Name = "Object One" };
// Act
var result = await controller.CreateObject(objectForCreationDto);
// Assert
Assert.IsType<OkObjectResult>(result);
}