.Net Core Web Api CRUD Controller unit testing code sample

By | November 15, 2017

Unit testing in .Net Core has been made simple. It has been designed with testability in mind. TDD approach has paid rich dividends for the developers who follow them religiously. Unit tests gives you the confidence and faith in your code, catches errors early in the cycle and overall, improves productivity levels across the team. There is a upfront cost with unit testing but, it’s worth the cost and effort. This code sample unit tests a typical CRUD web api controller. This code sample is compiled on .Net Core 2.0 and .Net Core Standard 2.0. We used xUnit as testing framework and test runner, Moq for mocking dependencies.


namespace VisualStudio99.Tests
{
public class EmployeeControllerTests
{
private readonly Mock<IEmployeeRepository> mockRepo;
private readonly Mock<EmployeeMapper> mockMapper;
private readonly EmployeeController controller;
public EmployeeControllerTests()
{
mockRepo = new Mock<IEmployeeRepository>();
mockMapper = new Mock<EmployeeMapper>();
controller = new EmployeeController(mockRepo.Object, mockMapper.Object);
}
[Fact]
public async Task Post_ReturnsOkResult_WhenCreatingValidEmployee()
{
// Arrange & Act

mockRepo.Setup(repo => repo.Add(It.IsAny<Employee>())).Verifiable();
mockRepo.Setup(repo => repo.SaveAsync()).ReturnsAsync(1);
mockRepo.Setup(repo => repo.AnyAsync(It.IsAny<Expression<Func<Employee, bool>>>())).Returns(Task.FromResult(false));
// Act
var result = await controller.Post(EmployeeData.GetNewEmployee());

//Assert
mockRepo.Verify(repo => repo.Add(It.IsAny<Employee>()), Times.Once);
mockRepo.Verify(repo => repo.SaveAsync(), Times.Once);
var createdAtRouteResult = Assert.IsType<CreatedAtActionResult>(result);
var employee = Assert.IsType<EmployeeDto>(createdAtRouteResult.Value);
Assert.Equal(“TestEmployee”, employee.Name);
}

[Fact]
public async Task Post_ReturnsBadRequest_WhenUpdatingInvalidNullEmployee()
{

// Act
var result = await controller.Post(null);

//Assert
mockRepo.Verify(repo => repo.Add(It.IsAny<Employee>()), Times.Never);
Assert.IsType<BadRequestObjectResult>(result);
}
[Fact]
public async Task Post_ReturnsBadRequest_WhenAddingExistingEmployee()
{

mockRepo.Setup(repo => repo.AnyAsync(It.IsAny<Expression<Func<Employee, bool>>>())).Returns(Task.FromResult(true));
// Act
var result = await controller.Post(EmployeeData.GetNewEmployee());

//Assert
mockRepo.Verify(repo => repo.Add(It.IsAny<Employee>()), Times.Never);
Assert.IsType<BadRequestObjectResult>(result);
}

[Fact]
public async Task Get_Returns_All_Employees()
{
// Arrange
mockRepo.Setup(repo => repo.GetAsync()).Returns(Task.FromResult(EmployeeData.GetEmployees()));

// Act
var result = await controller.GetAllAsync();

// Assert
var okResult = Assert.IsType<OkObjectResult>(result);
Assert.IsType<List<EmployeeDto>>(okResult.Value);
mockRepo.Verify(repo => repo.GetAsync(), Times.AtMostOnce);
}

[Theory]
[InlineData(1)]

public async Task Get_ReturnsHttpOkResult_ForValidEmployeeId(int empId)
{
// Arrange
string employeeName = “testEmployee”;
mockRepo.Setup(repo => repo.GetAsync(It.IsAny<Expression<Func<Employee, bool>>>())).Returns(Task.FromResult(EmployeeData.GetEmployees().Where(t => t.EmpId == empId).ToList()));

// Act
var result = await controller.Get(empId);

// Assert
var okResult = Assert.IsType<OkObjectResult>(result);
var emp = Assert.IsType<List<EmployeeDto>>(okResult.Value).FirstOrDefault();
mockRepo.Verify(repo => repo.GetAsync(It.IsAny<Expression<Func<Employee, bool>>>()), Times.Once);
Assert.True(emp.EmpName == employeeName);
}
[Fact]
public async Task Get_ReturnsBadRequestResult_ForInValidEmpId()
{
// Arrange
var empId = –1;
mockRepo.Setup(repo => repo.GetAsync(It.IsAny<Expression<Func<Employee, bool>>>())).Returns(Task.FromResult(EmployeeData.GetEmployees().Where(t => t.EmpId == empId).ToList()));

// Act
var result = await controller.Get(empId);

// Assert
Assert.IsType<BadRequestObjectResult>(result);
mockRepo.Verify(repo => repo.GetAsync(), Times.Never);
}

[Fact]
public async Task Put_ReturnsBadRequestResult_WhenUpdatingInvalidNullEmployee()
{
// Arrange & Act

// Act
var result = await controller.Put(null);

//Assert
mockRepo.Verify(repo => repo.Update(It.IsAny<Employee>()), Times.Never);
Assert.IsType<BadRequestObjectResult>(result);
}
[Fact]
public async Task Put_ReturnsNotFoundRequest_WhenUpdatingInvalidEmployee()
{
// Arrange & Act
mockRepo.Setup(repo => repo.AnyAsync(It.IsAny<Expression<Func<Employee, bool>>>())).Returns(Task.FromResult(false));
// Act
var result = await controller.Put(new EmployeeDto()
{
EmpId = 99
});

//Assert
mockRepo.Verify(repo => repo.Update(It.IsAny<Employee>()), Times.Never);
Assert.IsType<NotFoundResult>(result);
}
[Fact]
public async Task Put_ReturnsOkResult_WhenUpdatingValidEmployee()
{
// Arrange & Act
mockRepo.Setup(repo => repo.Update(It.IsAny<Employee>())).Verifiable();
mockRepo.Setup(repo => repo.SaveAsync()).ReturnsAsync(1);
mockRepo.Setup(repo => repo.AnyAsync(It.IsAny<Expression<Func<Employee, bool>>>())).Returns(Task.FromResult(true));
// Act
var result = await controller.Put(new EmployeeDto()
{
EmpId = 1
});

//Assert
mockRepo.Verify(repo => repo.Update(It.IsAny<Employee>()), Times.Once);
mockRepo.Verify(repo => repo.SaveAsync(), Times.Once);
Assert.IsType<NoContentResult>(result);
}
[Fact]
public async Task Delete_ReturnsHttpBadRequest_ForInvalidEmployee()
{
// Arrange
int empId = 99;
mockRepo.Setup(repo => repo.AnyAsync(It.IsAny<Expression<Func<Employee, bool>>>())).Returns(Task.FromResult(false));

// Act
var result = await controller.Delete(empId);

// Assert
Assert.IsType<BadRequestResult>(result);
}

[Fact]
public async Task Delete_ReturnsNoContentResult_ForValidEmployee()
{
// Arrange
int empId = 99;
mockRepo.Setup(repo => repo.AnyAsync(It.IsAny<Expression<Func<Employee, bool>>>())).Returns(Task.FromResult(true));
mockRepo.Setup(repo => repo.SaveAsync()).ReturnsAsync(1);

// Act
var result = await controller.Delete(empId);

// Assert
mockRepo.Verify(repo => repo.Delete(It.IsAny<int>()), Times.Once);
mockRepo.Verify(repo => repo.SaveAsync(), Times.Once);
Assert.IsType<NoContentResult>(result);
}

}
}

Leave a Reply

Your email address will not be published. Required fields are marked *