Reputation: 2800
I got an error when trying to use NSubstitute on my DbContext. So far I used the EntityFramework.Testing package and the following code to set up my DbContext in the tests. It was quite simple, here's a sample from their site:
// Create some test data
var data = new List<Blog>
{
new Blog{ Name = "BBB" },
new Blog{ Name = "CCC" },
new Blog{ Name = "AAA" }
};
// Create a DbSet substitute.
var set = Substitute.For<DbSet<Blog>, IQueryable<Blog>, IDbAsyncEnumerable<Blog>>()
.SetupData(data);
var context = Substitute.For<BloggingContext>();
context.Blogs.Returns(set);
This works nicely with version 3.1.0
, but throws the following exception if I upgrade NSubstitute to 4.0
.
System.MissingMethodException Method not found: 'System.__Canon NSubstitute.Arg.Any()'. NSubstitute.NSubstituteDbSetExtensions.SetupData[TEntity](DbSet'1 dbSet, ICollection'1 data, Func'2 find)
I wonder if there's a good solution to mock EF contexts with async support or should I just stick to 3.1.0.
Upvotes: 2
Views: 1134
Reputation: 1
[TestFixture]
public class InvoicesControllerTests
{
private InvoicesController _controller;
private BdAgendaTChampionContext _context;
[SetUp]
public void SetupInvoice()
{
// Mock the context
var options = new DbContextOptionsBuilder<BdAgendaTChampionContext>()
.UseInMemoryDatabase(databaseName: Guid.NewGuid().ToString())
.Options;
_context = new BdAgendaTChampionContext(options);
//// Seed the in-memory database with substitute data
_context.Invoices.AddRange(Substitute.For<Invoice>());
_context.InvoiceDetails.AddRange(Substitute.For<InvoiceDetail>());
_context.Customers.AddRange(Substitute.For<Customer>());
_context.SaveChanges();
// Initialize the controller
_controller = new InvoicesController(_context);
}
[TestFixture]
public class Update : InvoicesControllerTests
{
[Test]
public void InvoiceStatusID_ShouldReturnOK()
{
//Arrange
int vKey = 1;
var vUpdatedStatus = 30;
var vValue = new { InvoiceStatusId = vUpdatedStatus };
var vData = JsonConvert.SerializeObject(vValue);
//Act
var vResult = _controller.Update(vKey, vData);
//Asset
var vInvoice = _context.Invoices.First(i => i.InvId == vKey);
Assert.That(vUpdatedStatus, Is.EqualTo(vInvoice.StatusId));
Assert.That(vResult, Is.TypeOf<OkResult>());
}
}
Hi, I had the same problem with IQueryable. Here's a solution I came up with to set up and mock my context(instead of mocking my whole context I only mock the tables that i need for the controller that i want test), as well as how I proceeded afterward. I hope it helps with your issue.
Upvotes: 0