How to mock or substitute Entity Framework context in unit test?

c# entity-framework-6 mocking ninject unit-testing

Question

I want to unit test a piece of business logic in one of my projects.

BL:

public class CommunicationService
{
    IContext context;

    public CommunicationService()
    {
        var kernel = new StandardKernel(new NinjectConfig());
        context = kernel.Get<IContext>();
    }

    // This creates a file
    public void SomeMethodThatUsesIContext() { ... }
}

NinjectConfig:

class NinjectConfig : NinjectModule
{
    public override void Load()
    {
        Bind<IContext>().To<CommunicationDbContext>();
    }
}

the unit test

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

In the project for the unit test, I have another Ninject configuration:

class FakeNinjectConfig : NinjectModule
{
    public override void Load()
    {
        Bind<IContext>().To<FakeDbContext>();
    }
}

Additionally, I want the unit test to make advantage of this IContext implementation. However, the original CommunicationDbContext implementation is still used. I thought that if I have another ninject configuration here, the kernel would load it, but I now think that I may have misunderstood. Could you please aid me in that?

1
0
3/23/2016 4:19:06 PM

Accepted Answer

You have a problem since you produce kernel usingNinjectConfig in place ofFakeNinjectConfig in CommunicationService constructor.

public class CommunicationService
{
    IContext context;

    public CommunicationService()
    {
        var kernel = new StandardKernel(new NinjectConfig());
        context = kernel.Get<IContext>();
    }

simple method

To inject a new constructor, you can:NinjectModule or StandardKernel .

public CommunicationService (StandardKernel kernel) 
{
    context = kernel.Get<IContext>();
}

public CommunicationService(NinjectModule injectModule):this (new StandardKernel(injectModule))
{
    context = kernel.Get<IContext>();
}

public CommunicationService():this (new NinjectConfig())
{}

Additionally, you can use the constructor in the test to callFakeNinjectConfig .

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

Or

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

proper manner

However, in my opinion, you should add theIContext in the same way as injectIContext resolving CommunicationService .

public class CommunicationService
{
    IContext context;

    public CommunicationService(IContext _context)
    {
       context = _context;
    }

Secondly, when you make anCommunicationService You must utilizeGet alternative kernel technique to anew operator. For instance, as opposed tocommunicationService = new CommunicationService() You must utilizecommunicationService = Kernel.Get<CommunicationService>();

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

You could also inject.IContext directly

[TestMethod]
public void ScheduleTransportOrder_1()
{
    communicationService = new CommunicationService(new FakeDbContext());
    communicationService.SomeMethodThatUsesIContext();
    Assert.IsTrue(...) // file should be created.
}
2
3/23/2016 5:10:57 PM


Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow