question

Ocelot013 avatar image
0 Votes"
Ocelot013 asked Ocelot013 commented

Unit test uses shared database

I've implemented unit tests in my app, when I run my test individually all pass but when I run them individually I get some fail.

here is how I create InMemory db.

  public static DbContextOptionsBuilder<T> GetDbContextOptionsBuilder<T>( string? connectionString =null, bool enableLazyLoading = false , Guid? databaseId = null)
       where T : DbContext
     {
       var optionBuilder = new DbContextOptionsBuilder<T>();
       if (databaseId is null)
         databaseId = Guid.NewGuid();
       
       optionBuilder.UseInMemoryDatabase( $"Pm-api-{databaseId:N}")
                    .EnableSensitiveDataLogging()
                    .EnableDetailedErrors();
       return optionBuilder;
     }

And tests:

 [Fact]
     public async Task Can_Add_Product()
     {
       var             modelCode = "test";
       var             option    = DbContextInitialization.GetDbContextOptionsBuilder<MyDbContext>().Options;
       await using var db        = new MyDbContext(option , MediatorHelper.Initialize() );
       var             category  = db.SeedCategory();
       // Add product code removed for brevity
    
       var actualProduct = await db.Products.FirstAsync();
       actualProduct.ShouldNotBeNull();
       actualProduct.ModelCode.Value.ShouldEqual( modelCode );
     }
    
     [Fact]
     public async Task Can_Save_Add_Product()
     {
       var             option   = DbContextInitialization.GetDbContextOptionsBuilder<MyDbContext>().Options;
       await using var db       = new MyDbContext( option, MediatorHelper.Initialize() );
       var             category =db.SeedCategory();
       var             product  =db.SeedProduct(category);
       db.SeedServiceTypes();
       // Add product code removed for brevity
          
       var actualProduct = await db.Products.FirstAsync();
       //db.products now have two products, one is added in Can_Add_Product test and one is added with current test, which only one product should be available, if I run these two test indivudually then it passes.
     }


dotnet-aspnet-core-mvcdotnet-aspnet-core-webapidotnet-entity-framework
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

1 Answer

Bruce-SqlWork avatar image
0 Votes"
Bruce-SqlWork answered Ocelot013 commented

your tests need to roll back any data changes they make.

you can one of the following:

  • recreate the database before each test

  • truncate all tables before each test

  • begin a transaction and rollback rather than commit with each test

  • write the tests to not assume an empty database.

  • each test undos what it did


· 1
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

I prefer to recreate the database after each test,
now my question is by this line it doesn't create a database?

       await using var db       = new MyDbContext( option, MediatorHelper.Initialize() );

I tested it with .net 6.0 and it creates a new database, but i'm using .net core 3.1 and each test uses the same database, however I added databaseId = Guid.NewGuid() but it does not create a new one.

0 Votes 0 ·