views:

126

answers:

2

I am trying to set up expectations on methods of a mocked object in Moq. At the same time, using Ninject, I try to have the kernel return my set up mock whenever a caller wants the corresponding interface. For more clarity, here's some pseudocode

Class Car {

    Void buildChassis() {
        Engine = ObjectBuilder.get<Iengine>()
        Engine.performCheckup()
    }
}

When testing buildChassis, I want to plug in a mocked Engine.

Mock<Iengine>().setup().etc.etc.etc

However, Moq doesn't play nice with Ninject : I can't achieve this. I'm wondering if there are any robust software packages around which integrate both DI and mocking. I can't get the ninject.moq package working, nor does it seem to be mature.

+1  A: 

I use and like Moq, but use a different IoC container than Ninject. I've never felt the need to integrate mocking/isolation and IoC container frameworks. I use constructor injection, then simply pass mock objects to my classes in the unit tests. Only production code uses the container.

IMHO the real issue here is that Car knows about ObjectBuilder. Rather than using the container as a service locator, why not do constructor injection? That way only one top-level class needs to know anything about the IoC container.

class Car
{
    public Car(IEngine engine)
    {
        // May want a null check here
        Engine = engine;
    }

    public IEngine Engine { get; private set; }
}

Testing Car in isolation is easy; create a mock IEngine and pass it to the constructor.

You can pass in a factory interface if you need to create the engine at a later time.

If you decide to change to a different IoC framework, you only need to change one or two top-level classes.

TrueWill
Well, in some cases you really do need the equivalent of creating a new instance of a class, only to add it to a list, for example. How would you test in those cases ? (I have this need...)
Andrei Tanasescu
@Andrei: Inject an IEngineFactory with a method that creates IEngine instances (one way; you could also inject a delegate). Moq can mock the factory, then you set up the return value of the create method to return another mock.
TrueWill
See also http://www.tavaresstudios.com/Blog/post/Unity-20-Automatic-Factories.aspx - not sure if Ninject has this feature.
TrueWill
A: 

+1'd other answer - a big magic tool that makes everything just work is rarely the right answer. It's important to consider whether the fact that you have to do loads of setup in your test is trying to tell you something about the structure of your code. Also, you don't want to tie your tests to too much junk - ideally just to one unit at a time and think very carefully about any dependencies you add. If your context setup (Arrange) of your test goes of and does loads of generic stuff which isnt specific to your test, that's going to be a magnet for interdependencies and coincidences that snowball into a ball of mud. Ultimately that leads you to have to do stacks of rearranging on your test code whenever you want to adjust an aspect of your production code.

But there is http://github.com/ninject/ninject.moq

Ruben Bartelink