-
-
Notifications
You must be signed in to change notification settings - Fork 0
Testing Strategies
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.
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.
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");
}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:
- Testcontainers for .NET — to spin up disposable SQL containers.
- Respawn — to reset your database between tests.
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();
}- 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.