Skip to content

Testing Strategies

Casey edited this page Apr 6, 2025 · 2 revisions

EntityAxis is designed with testability in mind — all abstractions (ICreate, IUpdate, IGetById, etc.) are easily mockable or replaceable using dependency injection. This page provides helpful patterns and practices for testing applications that consume EntityAxis libraries.


🧪 Mocking Services

You can mock any of the abstractions using a mocking library like Moq or substitute a test double directly:

var mock = new Mock<IGetById<Product, Guid>>();
mock.Setup(x => x.GetByIdAsync(It.IsAny<Guid>(), default))
    .ReturnsAsync(new Product { Id = Guid.NewGuid(), Name = "Test Product" });

services.AddSingleton(mock.Object);

If you're writing unit tests for MediatR handlers or validators, mocking dependencies like IGetById or IMapper is straightforward.


🧼 Isolated Unit Testing

You can test command/query handlers, validators, and mapping logic independently.

[Fact]
public async Task CreateProductHandler_ShouldReturnNewId()
{
    // Arrange
    var mockCreate = new Mock<ICreate<Product, Guid>>();
    mockCreate.Setup(x => x.CreateAsync(It.IsAny<Product>(), default))
              .ReturnsAsync(Guid.NewGuid());

    var mockMapper = new Mock<IMapper>();
    mockMapper.Setup(m => m.Map<Product>(It.IsAny<ProductCreateModel>()))
              .Returns(new Product { Name = "Test Product" });

    var handler = new CreateEntityHandler<ProductCreateModel, Product, Guid>(mockCreate.Object, mockMapper.Object);

    // Act
    var result = await handler.Handle(new CreateEntityCommand<ProductCreateModel, Product, Guid>(new ProductCreateModel()), default);

    // Assert
    result.Should().NotBeEmpty();
}
[Fact]
public void ProductCreateModelValidator_ShouldFail_WhenNameIsEmpty()
{
    // Arrange
    var validator = new ProductCreateModelValidator();
    var model = new ProductCreateModel { Name = "" };

    // Act
    var result = validator.Validate(model);

    // Assert
    result.IsValid.Should().BeFalse();
    result.Errors.Should().Contain(e => e.PropertyName == "Name");
}

🧰 Use Real Databases for EF Core Testing

While EF Core’s UseInMemoryDatabase provider works for simple tests, it’s recommended to test against a real database for the most accurate results.

Tools we recommend:

public class DatabaseFixture : IAsyncLifetime
{
    private readonly MsSqlTestcontainer _container;

    public string ConnectionString => _container.ConnectionString;

    public DatabaseFixture()
    {
        _container = new TestcontainersBuilder<MsSqlTestcontainer>()
            .WithDatabase(new MsSqlTestcontainerConfiguration
            {
                Password = "yourStrong(!)Password"
            })
            .Build();
    }

    public async Task InitializeAsync() => await _container.StartAsync();
    public async Task DisposeAsync() => await _container.DisposeAsync();
}

✅ Summary

  • Mock EntityAxis interfaces for lightweight unit testing.
  • Override default services in DI during test setup.
  • Use a real database (with Testcontainers + Respawn) for integration tests.

📚 See Also

Clone this wiki locally