Skip to content

Latest commit

 

History

History

Atc.Rest.FluentAssertions

Atc.Rest.FluentAssertions

This library contains extensions to the FluentAssertions library, that makes it easier to assert against the ResultBase types returned from domain handlers.

Requirements

Code documentation

References

References extended

Included assertion methods

The domain handlers generated by ATC always return a type that inherits from ResultBase. That type is the extension point for the following assertion methods:

  • result.Should().BeOkResult(): Verifies that the result object is a OkObjectResult type with a status code of 200.

  • result.Should().BeAcceptedResult(): Verifies that the result object is a ContentResult type with a status code of 202.

  • result.Should().BeNoContentResult(): Verifies that the result object is a ContentResult type with a status code of 204.

  • result.Should().BeBadRequestResult(): Verifies that the result object is a ContentResult type with a status code of 400.

  • result.Should().BeNotFoundResult(): Verifies that the result object is a ContentResult type with a status code of 404.

  • result.Should().BeConflictResult(): Verifies that the result object is a ContentResult type with a status code of 409.

Getting the result object

To access the result object, use the standard Subject property, e.g. result.Should().BeOkResult().Subject. The usual standard FluentAssertions properties, such as Which, And, are also available where appropriate.

Verifying content

To help verify the content in a result, use the WithContent method, which accepts the expected content directly, e.g. result.Should().BeOkResult().WithContent(expected).

The "error result types", e.g. bad request and not found, also has a WithErrorMessage method, that helps verify a custom error messages.

Examples

The following example will show how to test the following a simple GetAllItemsByCategory handler:

public class GetAllItemsByCategoryHandler : IGetAllItemsByCategoryHandler
{
    private readonly IRepository repository;

    public GetAllItemsByCategoryHandler(IRepository repository)
    {
        this.repository = repository ?? throw new ArgumentNullException(nameof(repository));
    }

    public Task<GetAllItemsByCategoryResult> ExecuteAsync(GetAllItemsByCategoryParameters parameters, CancellationToken cancellationToken = default)
    {
        if (parameters is null)
        {
            throw new ArgumentNullException(nameof(parameters));
        }

        return InvokeExecuteAsync(parameters, cancellationToken);
    }

    private async Task<GetAllItemsByCategoryResult> InvokeExecuteAsync(GetAllItemsByCategoryParameters parameters, CancellationToken cancellationToken)
    {
        List<Item>? result = await repository.GetByCategory(parameters.Category);

        return result is not null
            ? GetAllItemsByCategoryResult.OK(result)
            : GetAllItemsByCategoryResult.NotFound("Invalid category");
    }
}

This handler basically uses a repository to try to find items based on a category. The repository will return null as the result if the category does not exist.

Using BeOkResult() to verify returned data

To verify the data returned from the repository is correctly returned from the handler, do the following:

[Fact]
public async Task Should_Return_OK_And_Content_From_Repository()
{
    // Arrange
    var items = new[] { new Item() { Category = "Foo" } };
    var repository = new FakeRepository(items);
    var sut = new GetAllItemsByCategoryHandler(repository);

    // Act
    var result = await sut.ExecuteAsync(new GetAllItemsByCategoryParameters { Category = "Foo" });

    // Assert
    result
        .Should()
        .BeOkResult()
        .WithContent(items);
}

In the above example, the BeOkResult method is used to verify that the result is a OkObjectResult type with a status code of 200. Then the WithContent method is used to verify that the content in the OK result is the same as the expected items collection.

The WithContent uses the BeEquivalentTo method from FluentAssertions that does a structural comparison, since the content in the OK result is serialized to JSON.

Using BeNotFoundResult() to verify NOT FOUND result

To verify that a 404 NOT FOUND response is returned when the repository returns null, do the following:

[Fact]
public async Task Should_Return_NotFound_When_Category_Isnt_In_Repository()
{
    // Arrange
    var repository = new FakeRepository();
    var sut = new GetAllItemsByCategoryHandler(repository);

    // Act
    var result = await sut.ExecuteAsync(new GetAllItemsByCategoryParameters { Category = "Bar" });

    // Assert
    result
        .Should()
        .BeNotFoundResult()
        .WithErrorMessage("Invalid category");
}

In the example above, the BeNotFoundResult method is used to check that the result type is a ContentResult type, with a status code of 404.

If you provide a custom error message to the NotFound method in the handler, this can be verified with the WithErrorMessage method, as shown here.