我如何使用NSubstitute模拟DbContext,然后添加/删除数据

本文关键字:添加 然后 删除 数据 DbContext 何使用 NSubstitute 模拟 | 更新日期: 2023-09-27 18:06:53

我需要模仿EF的DbContext。我在这里使用这种方法,效果很好。

// mock a DbSet
var mockDbSet = Substitute.For<DbSet<Foo>, IQueryable<Foo>>();
var data = new List<Foo>().AsQueryable();
((IQueryable<Foo>)mockDbSet).Provider.Returns(data.Provider);
((IQueryable<Foo>)mockDbSet).Expression.Returns(data.Expression);
((IQueryable<Foo>)mockDbSet).ElementType.Returns(data.ElementType);
((IQueryable<Foo>)mockDbSet).GetEnumerator().Returns(data.GetEnumerator());
// now add it to a mock DbContext
var mockContext = Substitute.For<MyDbContextClass>();
mockContext.Set<Foo>().Returns(mockDbSet);

然而,在一些测试中,我需要能够调用mockContext.Set<Foo>().Add(someFoo)mockContext.Set<Foo>().Remove(otherFoo),并为底层添加/删除逻辑工作。

我试过了:

mockDbSet.When(x => x.Add(Arg.Any<Foo>())).Do(x => data.Add(x.Arg<Foo>()));

但它抛出Collection was modified; enumeration operation may not execute.

那么我如何实现添加/删除功能呢?

我如何使用NSubstitute模拟DbContext,然后添加/删除数据

您不希望将其添加到集合中。你要做的是检查它(添加/删除/等)是否被调用,以及它是如何被调用的。

// arrange - check what it was called with. You place asserts in the body of the `Do` expression. Place this before your call that actually executes the code
mockDbSet.Add(Arg.Do<Foo>(foo =>
{
    Assert.IsNotNull(foo);
    // Assert other properties of foo
}));
// act

// assert. Make sure that it was actually called
mockDbSet.Received(1).Add(Arg.Any<Foo>());

如果您想在稍后的测试中添加Foo,您可以保留对FooList的引用。

// mock a DbSet
var mockDbSet = Substitute.For<DbSet<Foo>, IQueryable<Foo>>();
var fooList = new List<Foo>();
var data = fooList.AsQueryable();
// rest of your code unchanged
// add it from the code being tested through the mock dbset
mockDbSet.Add(Arg.Do<Foo>(foo =>
{
    fooList.Add(foo);
    // at this point you have to recreate the added IQueryable
    data = fooList.AsQueryable();
    // rest of code you had to add this to the mockDbSet
}));

// act

@Stilgar的评论让我研究了一下EntityFramework。测试库,解决了这个问题。

所以我用这个库替换了我的东西(少了一件需要担心的事情)。

相关文章: