How to isolate EF InMemory database per XUnit test

后端 未结 2 1487
无人共我
无人共我 2020-12-14 06:43

I am trying use InMemory EF7 database for my xunit repository test.

But my problem is that when i try to Dispose the created context the in memory db persist. It me

2条回答
  •  暗喜
    暗喜 (楼主)
    2020-12-14 06:47

    I think the answer Nate gave may be out of date now or maybe I am doing something wrong. UseInMemoryDatabase() now requires a db name.

    Below is what I ended up with. I added a line to create a unique db name. I removed the using statements in favor of using the constructor and dispose that are called once for each test case.

    There are some debug lines in there from my testing.

    public class DeviceRepositoryTests : IClassFixture, IDisposable
    {
    
        private readonly DeviceDbContext _dbContext;
        private readonly DeviceRepository _repository;
    
        private readonly ITestOutputHelper _output;
        DatabaseFixture _dbFixture;
    
        public DeviceRepositoryTests(DatabaseFixture dbFixture, ITestOutputHelper output)
        {
            this._dbFixture = dbFixture;
            this._output = output;
    
            var dbOptBuilder = GetDbOptionsBuilder();
            this._dbContext = new DeviceDbContext(dbOptBuilder.Options);
            this._repository = new DeviceRepository(_dbContext);
    
            DeviceDbContextSeed.EnsureSeedDataForContext(_dbContext);
            //_output.WriteLine($"Database: {_dbContext.Database.GetDbConnection().Database}\n" +
            _output.WriteLine($"" +
                  $"Locations: {_dbContext.Locations.Count()} \n" +
                  $"Devices: {_dbContext.Devices.Count()} \n" +
                  $"Device Types: {_dbContext.DeviceTypes.Count()} \n\n");
    
            //_output.WriteLine(deviceDbContextToString(_dbContext));
        }
    
        public void Dispose()
        {
            _output.WriteLine($"" +
                              $"Locations: {_dbContext.Locations.Count()} \n" +
                              $"Devices: {_dbContext.Devices.Count()} \n" +
                              $"Device Types: {_dbContext.DeviceTypes.Count()} \n\n");
            _dbContext.Dispose();
        }
    
        private static DbContextOptionsBuilder GetDbOptionsBuilder()
        {
    
            // The key to keeping the databases unique and not shared is 
            // generating a unique db name for each.
            string dbName = Guid.NewGuid().ToString();
    
            // Create a fresh service provider, and therefore a fresh 
            // InMemory database instance.
            var serviceProvider = new ServiceCollection()
                .AddEntityFrameworkInMemoryDatabase()
                .BuildServiceProvider();
    
            // Create a new options instance telling the context to use an
            // InMemory database and the new service provider.
            var builder = new DbContextOptionsBuilder();
            builder.UseInMemoryDatabase(dbName)
                   .UseInternalServiceProvider(serviceProvider);
    
            return builder;
        }
    

    Here is a very basic test case.

    [Fact]
    public void LocationExists_True()
    {
        Assert.True(_repository.LocationExists(_dbFixture.GoodLocationId));
    }
    

    I also made 8 of test cases that attempted to delete the same device with the same id and each passed.

提交回复
热议问题