admin管理员组

文章数量:1385002

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

本文标签: cXUnit run tests parallel and it cause problems with EF Core and SqliteStack Overflow