Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Override Ninject binding locally inside a test method to bind mock objects

I have the following problem, I want to use Ninject in my unit tests. My thoughts about this were like this:

1) Define a global binding schema inside a module to bind my fake objects that I use inside the tests

2) When using a mock object bind it locally inside the test

I didn't find a way to locally override the binding configuration, my idea is I locally create a mock object with expectations and I want the kernel.Get() method to return an object that has all the binding in place except that each tests adds a local mock object inside a test with expectations, this sounds to me to be readable and maintainable, as I only override 1 binding per test, the objects are mocks so they can't be configured inside the module as the test context is unknown

How can I accomplish this, I am using c# and nunit. If my methodology is wrong I would like to hear the right one.

like image 909
David MZ Avatar asked Sep 22 '11 12:09

David MZ


3 Answers

I have the same problem and I understand that it's not the good way to do but on my side, I do integration tests; not unit tests.

Here is my solution:

Kernel.Rebind<TypeToBind>().ToConstant(Mock.Object);

Where Kernel is the object that you used to create the binding. TypeToBind is the type that you want to inject dependency. Mock.Object is the object that you have previously setup.

Again, I know that it's not very cool but while working on legacy code where unit tests are hard to insert, this could be a salvation to have a good safety net.

like image 69
Samuel Avatar answered Nov 22 '22 08:11

Samuel


You shouldn't use your IoC container to create the object you want to test in your unit tests. Instead create it manually using new and pass a mock/stub object for each constructor argument.

like image 34
Remo Gloor Avatar answered Nov 22 '22 10:11

Remo Gloor


I think using IoC framework for tests is the perfect way to do it. In fact, that is why IoC existed in the first place and then frameworks came. Guice(google's java injection DI framework) actually supports this feature where you pass in the Module with the production bindings and then pass in a TestModule that can override certain bindings with mockobjects and then you can test away. We have been doing this and it has been very clean for a long time now in java. I am getting into myself just now to try to have my tests rebind stuff yet keep the rest of the bindings....

There are also frameworks like AtUnit where you are supposed to be using the DI framework to test the objects and NOT use the new keyword at all.(unfortunately, I don't see a port of that framework to C# land yet :( ).

NOTE: The reason this is desirable as when people add a new binding in production module and then use it in one of my system under test classes, it doesn't fail with nullpointer exceptions because an interface was not bound in the test. people keep adding and the test keeps working. In my opinion, you should only use the keyword "new" with dtos and such these days and all biz logic should be wired up with DI making it easy to add tests now or at a later point as well pretty easily(though I like to add tests first myself).

like image 38
Dean Hiller Avatar answered Nov 22 '22 09:11

Dean Hiller