Unit testing with EF Core and in memory database
It looks like you might want a class fixture.
When to use: when you want to create a single test context and share it among all the tests in the class, and have it cleaned up after all the tests in the class have finished.
Create a separate class to setup whatever data your tests will share, and to clean it up when the tests are finished running.
public class MovieSeedDataFixture : IDisposable
{
public MovieDbContext MovieContext { get; private set; } = new MovieDbContext();
public MovieSeedDataFixture()
{
MovieContext.Movies.Add(new Movie { Id = 1, Title = "Movie 1", YearOfRelease = 2018, Genre = "Action" });
MovieContext.Movies.Add(new Movie { Id = 2, Title = "Movie 2", YearOfRelease = 2018, Genre = "Action" });
MovieContext.Movies.Add(new Movie { Id = 3, Title = "Movie 3", YearOfRelease = 2019, Genre = "Action" });
MovieContext.SaveChanges();
}
public void Dispose()
{
MovieContext.Dispose();
}
}
Then use it in your tests by extending the IClassFixture<T>
interface.
public class UnitTests : IClassFixture<MovieSeedDataFixture>
{
MovieSeedDataFixture fixture;
public UnitTests(MovieSeedDataFixture fixture)
{
this.fixture = fixture;
}
[Fact]
public void TestOne()
{
// use fixture.MovieContext in your tests
}
}
You can resolve the issue by appending the timestamp with the name of database name.
var myDatabaseName = "mydatabase_"+DateTime.Now.ToFileTimeUtc();
var options = new DbContextOptionsBuilder<BloggingContext>()
.UseInMemoryDatabase(databaseName: myDatabaseName )
.Options;
Only one database with given name is created in memory. (Documentation) Hence if you have same name this kind of exception may occur.
Similar discussion is there on this thread:
optionsBuilder.UseInMemoryDatabase("MyDatabase");
This creates/uses a database with the name “MyDatabase”. If UseInMemoryDatabase is called again with the same name, then the same in-memory database will be used, allowing it to be shared by multiple context instances.
And this github issue also suggests the same approach to add a unique string with database name Hope this helps.
Thanks, I did some changes in the fixture class and is working fine, even when I run both tests together.
Here is the change:
public class MovieSeedDataFixture : IDisposable
{
public MovieDbContext MovieContext { get; private set; }
public MovieSeedDataFixture()
{
var options = new DbContextOptionsBuilder<MovieDbContext>()
.UseInMemoryDatabase("MovieListDatabase")
.Options;
MovieContext = new MovieDbContext(options);
MovieContext.Movies.Add(new Movie { Id = 1, Title = "Movie 1", YearOfRelease = 2018, Genre = "Action" });
MovieContext.Movies.Add(new Movie { Id = 2, Title = "Movie 2", YearOfRelease = 2018, Genre = "Action" });
MovieContext.Movies.Add(new Movie { Id = 3, Title = "Movie 3", YearOfRelease = 2019, Genre = "Action" });
MovieContext.SaveChanges();
}
public void Dispose()
{
MovieContext.Dispose();
}
}