Search code examples
c#unit-testingmoqxunitcqrs

How to do Unit Testing for a controller structured upon Clean Architecture and CQRS?


I have a Product API for which I mean to do Unit Testing via xUnit.net and Moq. I'm totally new to Unit Testing btw. I've seen a couple of videos on Unit Testing for controllers via Repository pattern, but This one is a CQRS. below is the presentation layer (API). I call commands or queries from the Application layer.

[HttpGet]
[AllowAnonymous]
public async Task<IActionResult> GetAllProducts()
{
    var products = await _mediator.Send(new GetAllProductsQuery());
    return Ok(products);
}

I wanted to test the Controller, so I added a reference to the API on the xUnit project. I tried to structure the commands and queries in the Application layer from the group up based on repository pattern but It failed!


Solution

  • Assuming (for the sake of simplicity) that _mediator is an instance of this IMediator interface, injected via the Controller's constructor:

    public interface IMediator
    {
        Task<IReadOnlyCollection<Product>> Send(GetAllProductsQuery getAllProductsQuery);
    }
    

    you can write a unit test of the Controller action like this:

    [Fact]
    public async Task GetAllProductsReturnsOk()
    {
        var td = new Mock<IMediator>();
        var expected = new[] { new Product() };
        td.Setup(m => m.Send(It.IsAny<GetAllProductsQuery>())).ReturnsAsync(expected);
        var sut = new ProductsController(td.Object);
    
        var result = await sut.GetAllProducts();
    
        var ok = Assert.IsAssignableFrom<OkObjectResult>(result);
        Assert.Equal(expected, ok.Value);
    }
    

    This test uses my standard test role names and AAA layout heuristic.