Reputation: 83
I want to test this (Controller Method) :
public async Task<IActionResult> Create(SecurityQuestionViewModel securityQuestion)
{
if (ModelState.IsValid)
{
SecurityQuestion dataModel = new SecurityQuestion();
dataModel.questionText = securityQuestion.QuestionText;
await _securityRepository.AddAsync(dataModel);
return RedirectToAction("Index");
}
else
{
return View();
}
}
My unit test (so far) looks like this ?
public async Task ModelContainsNewObjectAfterCreate()
{
//Arrange
_repository = new Mock<ISecurityQuestionRepository>();
_repository.Setup(repo => repo.GetAllAsync()).Returns(Task.FromResult(securityQuestion()));
_controller = new SecurityQuestionsController(_repository.Object, _mapper);
SecurityQuestion dataModel = new SecurityQuestion();
dataModel.questionText = "This is the new added question";
SecurityQuestionViewModel sqvm = new SecurityQuestionViewModel();
sqvm.QuestionText = dataModel.questionText;
//Act
var result = await _controller.Create(sqvm);
//Assert
var viewResult = Assert.IsType<RedirectToActionResult>(result);
_repository.Verify(r => r.AddAsync(dataModel), Times.Once);
}
The viewResult
passes.
The _repository
verify does not.
It feels like I need to verify that the AddAsync
method ran (would add a record to the existing repository). Perhaps my setup is wrong
It also feels like I need to validate the number of "questions" in the repository after the AddAsync
method ran.
I am trying to understand what would constitute an adequate test and how to simulate the "Add" with the Moq.
Any insight would be appreciated.
This Post seems close to what I want.
Upvotes: 1
Views: 304
Reputation: 5322
You can test only following things in your action:
There are only two cases. If the first case is satisfied you can verify that AddAsync()
is executed with any parameter which is type SecurityQuestion
.
You can mock AddAsync()
like this:
repository.Setup(r => r.AddAsync(It.IsAny<SecurityQuestion>())
.Returns(Task.FromResult(false));
And verify:
repository.Verify(r => r.AddAsync(It.IsAny<SecurityQuestion>()), Times.Once);
That is all which you can!
You cannot mock SecurityQuestion
model because it uses new
keyword and your code which try to mock should be removed.
This is all you need to do because your entire logic is if/else statement. Everything else will be executed normally. Only another thing which can behave unexpectedly is if AddAsync()
throws an exception.
Upvotes: 1
Reputation: 246998
The verify fails because the model was created within the method under test so it does not match. what you can do is use the It.Is
with a predicate that matches the model properties
_repository.Verify(r => r.AddAsync(It.Is<SecurityQuestion>(m => m.questionText == dataModel.questionText)), Times.Once);
Upvotes: 1