Reputation: 579
I am using IDbContextFactory
in a Blazor server application. I want to mock the services. I can do this using Moq, but when switching to NSubstitute, I run into a problem: only the Save
method in the service will pass, while all the rest fail with the following error:
System.ObjectDisposedException: cannot access a disposed context instance. A common cause of this error is disposing a context instance that was resolved from dependency injection and then later trying to use the same context instance elsewhere in your application. This may occur if you are calling 'Dispose' on the context instance, or wrapping it in a using statement. If you are using dependency injection, you should let the dependency injection container take care of disposing context instances.
Object name: 'LibraryContext'.
Here is my test setup with one of the test cases
public class AuthorServiceTests
{
private DbContextOptions<LibraryContext> CreateNewContextOptions()
{
return new DbContextOptionsBuilder<LibraryContext>()
.UseInMemoryDatabase(Guid.NewGuid().ToString())
.Options;
}
private IDbContextFactory<LibraryContext> GetDbContextFactory(DbContextOptions<LibraryContext> options)
{
var factory = Substitute.For<IDbContextFactory<LibraryContext>>();
factory.CreateDbContext().Returns(new LibraryContext(options));
return factory;
}
[Fact]
public async Task Save_ShouldAddAuthor()
{
// Arrange
var options = CreateNewContextOptions();
var factory = GetDbContextFactory(options);
var service = new AuthorService(factory);
var author = new Author { Name = "Author1", Phone = "123456789", Email = "[email protected]" };
// Act
await service.Save(author);
// Assert
using var context = new LibraryContext(options);
var savedAuthor = await context.Authors.FirstOrDefaultAsync(a => a.Name == "Author1");
Assert.NotNull(savedAuthor);
}
[Fact]
public async Task Delete_ShouldRemoveBook()
{
// Arrange
var options = CreateNewContextOptions();
var factory = GetDbContextFactory(options);
var service = new BookService(factory);
var book = new Book {Id = 1, Title = "Book1", ISBN = "1234567890", NumberOfPages = 500, Language = "Arabic" };
await service.Save(book);
// Act
await service.Delete(book);
// Assert
using var context = new LibraryContext(options);
var deletedBook = await context.Books.FindAsync(book.Id);
Assert.Null(deletedBook);
}
}
If I change to Moq everything works fine:
private IDbContextFactory<LibraryContext> GetDbContextFactory(DbContextOptions<LibraryContext> options)
{
var mockFactory = new Mock<IDbContextFactory<LibraryContext>>();
mockFactory.Setup(f => f.CreateDbContext()).Returns(() => new LibraryContext(options));
return mockFactory.Object;
}
I think there is an issue of how NSubstitute creates the subs for the method CreateDbContext
from IDbContextFactory
.
Any ideas on how to replicate the same behavior of Moq using NSubstitute?
Upvotes: 0
Views: 80