Home > database >  How to Put method using xUnit
How to Put method using xUnit

Time:01-11

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:

  1. 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
  2. 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
  3. 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);.

  • Related