I try to test Update method using xUnit and i dont know how to do it below is my code:
Put method in controller:
[HttpPut]
[Route("{id}")]
public IActionResult Put([FromBody]BookDto book, [FromRoute]int id)
{
if (!ModelState.IsValid)
{
return BadRequest();
}
var isUpdated = _service.Update(book);
if (!isUpdated)
{
return NotFound();
}
return Ok();
}
BookService update method:
public bool Update(BookDto book)
{
var bookDb = _context.Books.FirstOrDefault(x => x.Id == book.Id);
if(bookDb == null)
{
return false;
}
bookDb.Title = book.Title;
_context.SaveChanges();
var existingAuthors = _context.Book_Authors.Where(x => x.BookId == book.Id).ToList();
_context.Book_Authors.RemoveRange(existingAuthors);
_context.SaveChanges();
foreach (var AuthorsId in book.AuthorsId)
{
var newBookAuthors = new Book_Author()
{
BookId = book.Id,
AuthorId = AuthorsId
};
_context.Book_Authors.Add(newBookAuthors);
}
_context.SaveChanges();
return true;
}
BookDto:
public class BookDto
{
public int Id { get; set; }
public string Title { get; set; }
public List<int> AuthorsId { get; set; }
}
any suggestions how to write PutMethod test using Moq ?
CodePudding user response:
I would suggest to collect the test cases:
- Given an invalid book When I call put Then It returns bad request
- Given a non-existing book When I call put Then It returns not Found
- Given an existing book When I call put Then It returns ok
I would suggest to AAA pattern for each test case, for example:
- Arrange: Setup a book service mock which returns false whenever someone calls the update
- Act: Call your controller's put method
- Assert: Verify that the returned result is not found as expected
Try to codify. For example
public void GivenANonExistingBook_WhenICallPut_ThenItReturnsNotFound()
{
//Arrange
var book = ...;
var serviceMock = new Mock<IBookService>();
serviceMock.Setup(svc => svc.Update(It.IsAny<BookDto>()))
.Returns(false);
var sut = new YourController(serviceMock.Object);
//Act
var result = sut.Put(book, 0);
//Assert
var actionResult = result as NotFoundResult;
Assert.IsNotNull(actionResult);
}
It is also a good practice to verify that the Update
method of the service has been called only once with the book
variable: serviceMock.Verify(svc => svc.Update(book), Times.Once);
.