How to Unit Test Delete operation using moq and xUnit?

92 Views Asked by At

I'm trying to Unit Test CRUD operations for an API in my WEB API project. I have a hard time figuring out how to do that for DELETE. Below is my service;

public async Task DeleteCompany(int id)
{
    var query = "DELETE FROM Companies WHERE Id = @Id";
    using(var connection = _context.CreateConnection())
    {
        await connection.ExecuteAsync(query, new {id});
    }
}

Here's the controller

[HttpDelete("{id}")]
public async Task<IActionResult> DeleteCompany(int id)
{
    var company = await _companyRepository.GetCompanyById(id);
    if (company == null)
    {
        return NotFound();
    }
    await _companyRepository.DeleteCompany(id);
    return NoContent();
}

And below is the code for Unit Testing

[Theory]
[InlineData(1)]
public async Task CompanyController_DeleteCompany_ShouldReturnStatusCode204(int id)
{
    var mockCompany = new Mock<ICompanyRepository>();
    mockCompany.Setup(service => service.DeleteCompany(id))
           .Returns(Task.CompletedTask)
           .Verifiable();

    var sut = new CompanyController(mockCompany.Object);

    var result = (OkObjectResult) await sut.DeleteCompany(id);

    result.StatusCode.Should().Be(204);
}

It turned out that it returns a null value of my model (Company in this example) after debugging. That's why the test doesn't pass and it gets to NotFound error in the controller.

1

There are 1 best solutions below

0
Mark Seemann On BEST ANSWER

You need to set up the Test Double's GetCompanyById method so that it doesn't return null:

[Theory]
[InlineData(1)]
public async Task CompanyController_DeleteCompany_ShouldReturnStatusCode204(int id)
{
    var mockCompany = new Mock<ICompanyRepository>();
    mockCompany.Setup(service => service.GetCompanyById(id))
        .ReturnsAsync(/*pass non-null value here*/);
    var sut = new CompanyController(mockCompany.Object);

    var result = (OkObjectResult) await sut.DeleteCompany(id);

    result.StatusCode.Should().Be(204);
    mockCompany.Verify(service => service.DeleteCompany(id);
}

On the other hand, you don't need to set up DeleteCompany as a verifiable action since it doesn't return anything anyway. Mocks for Commands, Stubs for Queries. Use mockCompany.Verify instead, as shown above.