C# 如何在单元测试中模拟或替换实体框架上下文?

C# 如何在单元测试中模拟或替换实体框架上下文?,c#,unit-testing,mocking,entity-framework-6,ninject,C#,Unit Testing,Mocking,Entity Framework 6,Ninject,我想在我的一个项目中对业务逻辑组件进行单元测试 基本法: 我在单元测试的项目中有另一个Ninject配置: class FakeNinjectConfig : NinjectModule { public override void Load() { Bind<IContext>().To<FakeDbContext>(); } } 类FakeNinjectConfig:NinjectModule { 公共覆盖无效负载() { 绑

我想在我的一个项目中对业务逻辑组件进行单元测试

基本法:

我在单元测试的项目中有另一个Ninject配置:

class FakeNinjectConfig : NinjectModule
{
    public override void Load()
    {
        Bind<IContext>().To<FakeDbContext>();
    }
}
类FakeNinjectConfig:NinjectModule { 公共覆盖无效负载() { 绑定()到(); } }
我想在单元测试中使用IContext的这个实现。但它仍然使用原始的、可通信的bContext实现。我相信,当我在这里有另一个ninject配置时,它将被加载到内核,但我想现在我误解了一些东西。你能帮我一下吗?

问题是你使用
NinjectConfig
而不是
CommunicationService
构造函数中的
FakeNinjectConfig
创建内核

public class CommunicationService
{
    IContext context;

    public CommunicationService()
    {
        var kernel = new StandardKernel(new NinjectConfig());
        context = kernel.Get<IContext>();
    }
在测试中,您可以使用
FakeNinjectConfig
调用构造函数

[TestMethod]
public void ScheduleTransportOrder_1()
{
    communicationService = new CommunicationService(new FakeNinjectConfig ());
    communicationService.SomeMethodThatUsesIContext();
    Assert.IsTrue(...) // file should be created.
}

正确的方法:

但在我看来,您应该添加
IContext
作为依赖项,并注入
IContext
解析
CommunicationService

public class CommunicationService
{
    IContext context;

    public CommunicationService(IContext _context)
    {
       context = _context;
    }
然后,当您创建
CommunicationService
时,应该使用内核的
Get
方法,而不是
new
操作符。例如,代替
communicationService=newcommunicationservice()
您应该使用
communicationService=Kernel.Get()


问题是您使用
NinjectConfig
而不是
CommunicationService
构造函数中的
FakeNinjectConfig
创建内核

public class CommunicationService
{
    IContext context;

    public CommunicationService()
    {
        var kernel = new StandardKernel(new NinjectConfig());
        context = kernel.Get<IContext>();
    }
在测试中,您可以使用
FakeNinjectConfig
调用构造函数

[TestMethod]
public void ScheduleTransportOrder_1()
{
    communicationService = new CommunicationService(new FakeNinjectConfig ());
    communicationService.SomeMethodThatUsesIContext();
    Assert.IsTrue(...) // file should be created.
}

正确的方法:

但在我看来,您应该添加
IContext
作为依赖项,并注入
IContext
解析
CommunicationService

public class CommunicationService
{
    IContext context;

    public CommunicationService(IContext _context)
    {
       context = _context;
    }
然后,当您创建
CommunicationService
时,应该使用内核的
Get
方法,而不是
new
操作符。例如,代替
communicationService=newcommunicationservice()
您应该使用
communicationService=Kernel.Get()


这个问题实际上源于您在
CommunicationService
构造函数中执行
新标准内核(new NinjectConfig())
这一事实。我不确定您的逻辑是什么,但实际上,您永远无法使用当前代码向
通信服务提供模拟的
IContext
。我将研究使用Ninject的构造函数注入,并将
IContext
自动注入到
CommunicationService
中,这意味着您可以在测试中提供一个模拟实例。问题实际上源于您正在执行
新标准内核(new NinjectConfig())
在您的
通信服务中。我不确定您的逻辑是什么,但实际上,您永远无法使用当前代码向
通信服务提供模拟的
IContext
。我将研究使用Ninject的构造函数注入,并将
IContext
自动注入到
CommunicationService
中,这意味着您可以在测试中提供模拟实例。
[TestMethod]
public void ScheduleTransportOrder_1()
{
    communicationService = new CommunicationService(new StandardKernel(new FakeNinjectConfig ()));
    communicationService.SomeMethodThatUsesIContext();
    Assert.IsTrue(...) // file should be created.
}
public class CommunicationService
{
    IContext context;

    public CommunicationService(IContext _context)
    {
       context = _context;
    }
[TestMethod]
public void ScheduleTransportOrder_1()
{
    var testKernel = new StandardKernel(new FakeNinjectConfig ());
    communicationService = testKernel.Get<CommunicationService>();
    communicationService.SomeMethodThatUsesIContext();
    Assert.IsTrue(...) // file should be created.
}
[TestMethod]
public void ScheduleTransportOrder_1()
{
    communicationService = new CommunicationService(new FakeDbContext());
    communicationService.SomeMethodThatUsesIContext();
    Assert.IsTrue(...) // file should be created.
}