NSubstitute 替代 EF 的 Core DbContext - 如何使用它?

Ton*_*ony 2 nsubstitute ef-core-3.1

我正在尝试为使用我的类创建单元测试EF Core DbContext

public class MyContext : DbContext
{
    public MyContext(DbContextOptions<MyContext> options) : base(options)
    {
    }

    public DbSet<SomeTable> SomeTables { get; set; }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        ...
    }
}
Run Code Online (Sandbox Code Playgroud)

消耗该上下文的类很简单:

public class MyClass
{
    public MyClass(MyContext db)
    {
    }
}
Run Code Online (Sandbox Code Playgroud)

所以,当我尝试创建

var fakeContext = Substitute.For<MyContext>();
Run Code Online (Sandbox Code Playgroud)

以错误结束:

Castle.DynamicProxy.InvalidProxyConstructorArgumentsException : Can not instantiate proxy of class: MyContext.
Could not find a parameterless constructor.
Run Code Online (Sandbox Code Playgroud)

这是由构造函数引发的base(options)。因此,网络方法是扩展代码:

var dbContextOptions = Substitute.For<DbContextOptions<MyContext>>();

dbContextOptions.ContextType.Returns(typeof(MyContext));

var dbContextOptionsExtension = Substitute.For<IEnumerable<IDbContextOptionsExtension>>();
dbContextOptions.Extensions.Returns(dbContextOptionsExtension);

var myFakeContext = Substitute.For<MyContext>(dbContextOptions);
Run Code Online (Sandbox Code Playgroud)

但它会产生更多错误。那么,如何解决呢?

rgv*_*lee 5

您没有详细说明其他错误,因此我无法提供具体答案,但是尝试正确模拟 DbContext 很困难。国际海事组织有两种选择。

1) 使用Microsoft 内存提供程序

2) 如果您想使用 NSubstitute 来使用模拟的 DbContext,请使用一个预先存在的库来为您进行模拟。周围有一些,例如EntityFrameworkCore.Testing.NSubstitute(免责声明 - 我是作者)。

内存提供程序不是一个完整的实现,它无法执行关系操作,并且它不支持大量 LINQ 操作,因此根据您的用例,后者可能是更好的解决方案。

如果您有特定的错误/用例,请将其弹出,我也许能够提供更好的答案。