I am testing a class that uses a DbContext. This class gets an IDbContextFactory injected, which is then used to get a DbContext:
protected readonly IDbContextFactory<SomeDbContext> ContextFactory;
public Repository(IDbContextFactory<SomeDbContext> contextFactory)
{
ContextFactory = contextFactory;
}
public List<T> Get()
{
using var db = ContextFactory.CreateDbContext();
return db.Set<T>().ToList();
}
I am able to set things up for ONE test, but I have to call the Mock<DbContextFactory>.Setup(f => f.CreateDbContext()) method every time I want to use the context.
Here is an example:
var mockDbFactory = new Mock<IDbContextFactory<SomeDbContext>>();
mockDbFactory.Setup(f => f.CreateDbContext())
.Returns(new SomeDbContext(new DbContextOptionsBuilder<SomeDbContext>()
.UseInMemoryDatabase("InMemoryTest")
.Options));
var repository = new Repository<SomeEntity>(mockDbFactory.Object);
// non-existent id
Assert.IsNull(repository.Get(-1));
This works fine. However, if I add another repo call (like Assert.DoesNotThrow(() => repository.Get(1);), I get
System.ObjectDisposedException: Cannot access a disposed context instance.
If I call the Mock<T>.Setup() again, all works fine
var mockDbFactory = new Mock<IDbContextFactory<SomeDbContext>>();
mockDbFactory.Setup(f => f.CreateDbContext())
.Returns(new SomeDbContext(new DbContextOptionsBuilder<SomeDbContext>()
.UseInMemoryDatabase("InMemoryTest")
.Options));
var repository = new Repository<SomeEntity>(mockDbFactory.Object);
// non-existent id
Assert.IsNull(repository.Get(-1));
mockDbFactory.Setup(f => f.CreateDbContext())
.Returns(new SomeDbContext(new DbContextOptionsBuilder<SomeDbContext>()
.UseInMemoryDatabase("InMemoryTest")
.Options));
// pass
Assert.DoesNotThrow(() => repository.Get(1));
This is the Get(int id) method:
public T Get(int id)
{
using var db = ContextFactory.CreateDbContext();
return db.Set<T>().Find(id);
}
As far as I understand, Mock is setup to return
new SomeDbContext(new DbContextOptionsBuilder<SomeDbContext>()
.UseInMemoryDatabase("InMemoryTest")
.Options)
Every time .CreateDbContext() is called. To me, this means that it should return a new instance of the context every time, rather than the one that has already been disposed. However, it looks like it is returning the same disposed instance.