I am using XUnit with EF Core and Sqlite in .NET 9.
During testing, several tests add data to the database and since they do it in parallel and add data in parallel, the tests get unexpected data from the database. For example, I add 2 entities (rows) to an empty database, but in the next line I get 5 entities (rows) from the database.
This is how I create the DbContext
:
public class DataContextFactory : IDisposable
{
private readonly SqliteConnection _connection;
public DataContextFactory()
{
_connection = new SqliteConnection("Filename=:memory:");
_connection.Open();
}
public DataContext Create()
{
var options = new DbContextOptionsBuilder<DataContext>()
.UseSqlite(_connection)
.Options;
var context = new DataContext(options);
context.Database.EnsureDeleted();
context.Database.EnsureCreated();
return context;
}
public void Dispose()
{
_connection.Dispose();
GC.SuppressFinalize(this);
}
}
And here's how I used it in the tests:
public abstract class CrudRepositoryTests<TTestEntity> : IDisposable
where TTestEntity : BaseEntity
{
private readonly DataContextFactory _dataContextFactory;
public CrudRepositoryTests()
{
_dataContextFactory = new DataContextFactory();
DataContext = _dataContextFactory.Create();
}
protected DataContext DataContext { get; }
public void Dispose()
{
DataContext.Dispose();
_dataContextFactory.Dispose();
GC.SuppressFinalize(this);
}
[Fact]
public virtual async Task GetAllAsync_ShouldReturnAllEntities()
{
// Arrange
var (context, repository) = GetContextAndRepository(); // here it also returns DataContext, I just refactored the code
var test = await repository.GetAllAsync(); // here 0 is returned
var entities = await SetTestEntitiesAsync(context); // here I set 2 entities in the database and return them
// Act
var result = await repository.GetAllAsync(); // here I take 5 rows
// Assert
Assert.Equal(entities.Count, result.Count());
}
// other tests ...
protected async Task<ICollection<TTestEntity>> SetTestEntitiesAsync(DataContext context)
{
var entities = await context.Set<TTestEntity>().ToListAsync(); // returned 0 entities
if (entities.Count != 0)
{
return entities;
}
var newEntities = GetEntitiesToAdd(); // got 2 entities
context.Set<TTestEntity>().AddRange(newEntities); // added 2 entities
await context.SaveChangesAsync();
var test = await context.Set<TTestEntity>().ToListAsync(); // 5 entities returned here, why??? I think because parallel tests also add some rows to the database
return newEntities;
}
}
I've also attached an image that shows that I got an unexpected behavior in the SetTestEntitiesAsync
method.
Debug image
The image shows the additional code as context.Database.EnsureCreated()
, but I also tested without the added code.
If I can add any information, let me know!
Thanks
I tried to:
- Use
.EnsureDeleted' and
.EnsureCreated'. - Dispose (
Dispose()
) everything I could. - Use
[assembly: CollectionBehavior(DisableTestParallelization = true)]
But nothing helped me