用N代替EF的核心DbContext-如何使用它?

时间:2020-04-24 13:27:52

标签: 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)
    {
        ...
    }
}

使用该上下文的类很简单:

public class MyClass
{
    public MyClass(MyContext db)
    {
    }
}

所以,当我尝试创建

var fakeContext = Substitute.For<MyContext>();

以错误结尾:

Castle.DynamicProxy.InvalidProxyConstructorArgumentsException : Can not instantiate proxy of class: MyContext.
Could not find a parameterless constructor.
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);

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

2 个答案:

答案 0 :(得分:2)

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

1)使用Microsoft in-memory provider

2)如果要使用NSubstitute使用模拟的DbContext,请使用为您进行模拟的预先存在的库。诸如EntityFrameworkCore.Testing.NSubstitute之类的东西周围(免责声明-我是作者)。

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

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

答案 1 :(得分:1)

好的,我使用过InMemory提供程序:

var options = new DbContextOptionsBuilder<AgreementContext>()
                .UseInMemoryDatabase("fakeDb")
                .Options;

var agreementContext = Substitute.For<MyContext>(options);