Unit Test and Mock Sync/Async Controller Methods in ASP.NET Core
Today in this article, we will see how to Unit Test and Mock Sync/Async Controller Methods in ASP.NET Core.
Below is an example of the .NET Core unit testing sample for any controller method and their resolution using mocking.
Before we begin writing unit test cases for the controller, the first thing you should understand is that “Controller” is not special when it comes to unit testing.
Today in this article, we will cover below aspects,
The controller is simply a class like any other class which has members like methods and properties etc. The only thing we do a bit differently in controller unit testing is that of the REST response assertion.
Controller methods always return HTTP responses with resource details by following the REST principles.
We shall be using the same naming conventions for unit testing that we learned in our last article,
Asynchronous method
Here I am testing an async controller Method that also makes a call to an external service.
[HttpGet]
public async Task<IActionResult> GetAsync(string id)
{
Book book = null;
try
{
// await method - Asynchronously
book = await _bookService.GetAsync(id);
if (book == null)
{
return NotFound();
}
book.Price = 10;
}
catch(Exception ex)
{
throw;
}
// do more stuff
return Ok(book);
}
Asynchronous Controller – Mock and Unit Test
Below is an example of how we can write unit test cases for Asynchronous methods.
Here in the below example, I am following the same naming convention for Unit testing we learned in our last article.
Synchronous Controller Mock and Unit Test
Here below is an example of the Synchronous controller Method which also makes a call to an external service.
[HttpGet]
public ActionResult<Book> Get(string id)
{
var book = _bookService.Get(id);
book.Price = 10;
if (book == null)
{
return NotFound();
}
return Ok(book);
}
Resolution
Below is an example of how we can write unit test cases for Sync methods,
[Fact]
public void BookService_GetBookSync_With_ValidBookID()
{
//Arrange
Book document = new Book()
{
Author = "The",
BookName = "CodeBUzz",
Id = "1234"
};
string bookID = "1234";
var mockBookClient = new Mock<IBookService>();
mockBookClient.Setup(c => c.Get(document.Id))
.Returns(document);
//Act
BooksController service = new BooksController(mockBookClient.Object);
var result = service.Get(bookID).Result as ObjectResult;
var actualtResult = result.Value;
//Assert
//Return proper HTTPStatus code
Assert.IsType<OkObjectResult>(result);
//OR
Assert.Equal(HttpStatusCode.OK, (HttpStatusCode)result.StatusCode);
//Addtional asserts
Assert.Equal(document.Author, ((Book)actualtResult).Author);
Assert.Equal(document.BookName, ((Book)actualtResult).BookName);
Assert.Equal(document.Id, ((Book)actualtResult).Id);
}
Do you have any better suggestions to make our Controller methods more robust?
What to test in Controller Unit Testing?
Please note below a few helpful guidelines for Controller Unit testing.
- Controller methods should be unit tested like any other regular methods.
- Controller methods should be unit tested using assert for REST HTTP Status code.
- Use HttpStatusCode enum to assert the actual result type.
- Example 1
Assert.Equal(HttpStatusCode.OK, (HttpStatusCode)result.StatusCode);
- Example 2
Assert.IsType<OkObjectResult>(result);
Above, either way, the Unit tests make our API robust and validate implementation for the REST principle.
Each controller method should be asserted for all possible types of HTTP status codes like 200, 401, 200, 500 status codes, etc. These assertions will assure that the Controller method produces proper results.
- If the controller method is returning resources, such resources should be validated for their structure.
- This will assure that the code follows a contract properly when the consumer consumes your API.
- This schema assertion will red flag the code while development if there are any breaking changes.
- Always assert if mocked methods are invoked at least once.
- Example:
mockBookClient.Verify(c => c.GetAsync(It.IsAny()), Times.Once);
References:
Do you have any other better suggestions to test the method?
Please sound off your comments below!
Please bookmark this page and share it with your friends. Please Subscribe to the blog to receive notifications on freshly published(2024) best practices and guidelines for software design and development.