使用Ninject时如何基于接口模拟Context?

How to mock the Context based on an interface when using Ninject?

我有正常的 Entity Framework 上下文,是这样的:

public class LikvidoWebsitesApiContext : IdentityDbContext<ApplicationUser>, ILikvidoWebsitesApiContext
{   
   // code
}

我做了一个界面,里面有我的DBSets

在我的正常解决方案中,我在 Ninject 中设置如下:

kernel.Bind<ILikvidoWebsitesApiContext>().To<LikvidoWebsitesApiContext>().InRequestScope();

我通过在构造函数中添加 ILikvidoWebsitesApiContext 在我的服务中使用上下文,然后我可以使用数据库。

我的问题是:如何在单元测试中设置它?

我已尝试执行以下操作:

kernel.Bind(typeof(ILikvidoWebsitesApiContext))
            .To(typeof(Mock<LikvidoWebsitesApiContext>))
            .Register(true);

(使用Moq框架)

然而,这给出了:

System.InvalidCastException: 'Unable to cast object of type 'Moq.Mock`1[Likvido.Domain.Services.Data.LikvidoWebsitesApiContext]' to type 'Likvido.Domain.Services.Data.ILikvidoWebsitesApiContext'.'

哪个确实有意义,但我不确定如何解决它?

快速浏览 Ninject wiki 后,我发现了

Providers, Factory Methods and the Activation Context

他们展示了如何使用 Provider 构建实例。

根据 wiki 中的建议,建议扩展 Provider<T>,其中包括强类型。

public MoqContextProvider : Provider<ILikvidoWebsitesApiContext> {
    protected override ILikvidoWebsitesApiContext CreateInstance(IContext context) {
        var mock = new Mock<ILikvidoWebsitesApiContext>();

        // Set up of mock members

        return mock.Object;
    }
}

然后只需插入容器即可

kernel.Bind<ILikvidoWebsitesApiContext>().ToProvider(new MoqContextProvider());

还有关于使用 工厂方法

的建议

A lighter weight alternative to writing IProvider implementations is to bind a service to a delegate method.

kernal.Bind<ILikvidoWebsitesApiContext>()
    .ToMethod(context => {
        var mock = new Mock<ILikvidoWebsitesApiContext>();

        // Set up of mock members

        return mock.Object;    
    });

所提供的 Func 将绑定到延迟绑定的服务类型,并在需要新的服务实例(即 ILikvidoWebsitesApiContext)时调用。

请记住,在使用 Moq 时,您需要设置所需的模拟行为。