Reputation: 2166
I would like to unit test a business logic component 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>();
}
}
Unit test:
[TestMethod]
public void ScheduleTransportOrder_1()
{
communicationService = new CommunicationService();
communicationService.SomeMethodThatUsesIContext();
Assert.IsTrue(...) // file should be created.
}
I have another Ninject config in the unit test's project:
class FakeNinjectConfig : NinjectModule
{
public override void Load()
{
Bind<IContext>().To<FakeDbContext>();
}
}
And I want this implementation of IContext to be used in the unit test. But it still uses the original, CommunicationDbContext implementation. I believed, when I have another ninject configuration here, that will be loaded to the kernel, but I think now I misunderstood something. Could you help me with that?
Upvotes: 1
Views: 1417
Reputation: 5488
The problem is that you create kernel using NinjectConfig
instead of FakeNinjectConfig
in CommunicationService
constructor.
public class CommunicationService
{
IContext context;
public CommunicationService()
{
var kernel = new StandardKernel(new NinjectConfig());
context = kernel.Get<IContext>();
}
Simple way:
You can create a new constructor to inject a 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())
{}
And in the test you can call the constructor with FakeNinjectConfig
.
[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 way:
But in my point of view, you should add the IContext
as dependency and inject IContext
resolving CommunicationService
.
public class CommunicationService
{
IContext context;
public CommunicationService(IContext _context)
{
context = _context;
}
And then, when you create an CommunicationService
you should use Get
method of kernel instead of a new
operator. For example, instead of
communicationService = new CommunicationService()
you should use communicationService = 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.
}
Or you can inject IContext
directly
[TestMethod]
public void ScheduleTransportOrder_1()
{
communicationService = new CommunicationService(new FakeDbContext());
communicationService.SomeMethodThatUsesIContext();
Assert.IsTrue(...) // file should be created.
}
Upvotes: 2