最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

c# - XUnit run tests parallel and it cause problems with EF Core and Sqlite - Stack Overflow

programmeradmin3浏览0评论

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

发布评论

评论列表(0)

  1. 暂无评论