Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mocking without IoC or Dependency Injection

Is there a way to use mocks or fakes in your unit tests without having to use dependency injection or inversion or control?

I found this syntax can be used with TypeMock Isolator (http://learn.typemock.com/). It is a comercial product though, so I was hoping that other frameworks (such as RhinoMocks) would be introducing such syntax at some stage.

/// Can mock objects WITHOUT DEPENDENCY INJECTION.

var hand = Isolate.Fake.Instance<Hand>();
var mouth = Isolate.Fake.Instance<Mouth>();
Isolate.Swap.NextInstance<Hand>().With(hand);
Isolate.Swap.NextInstance<Mouth>().With(mouth);
...
//notice we're not passing the mocked objects in.
var brain = new Brain();
brain.TouchIron(iron);
...

This is very attractive to me this type of syntax, it all happens automatically. We can create a brain there with no required dependencies being passed in and the mocking framework will substitute the dependencies automatically for the mock objects. Any body seen this type of thing anywhere else?

The brain class constructor looks like this now using the above syntax,

public Brain()
{
    _hand = new Hand();
    _mouth = new Mouth();
}

Whereas the dependency injection example would look like this,

public Brain(IHand hand, IMouth mouth)
{
    _hand = hand;
    _mouth = mouth;
}

Thanks.

like image 286
peter Avatar asked Oct 14 '09 04:10

peter


People also ask

Is mocking a dependency injection?

Dependency injection is a way to scale the mocking approach. If a lot of use cases are relying on the interaction you'd like to mock, then it makes sense to invest in dependency injection. Systems that lend themselves easily to dependency injection: An authentication/authorization service.

When should you not use a mock?

Only use a mock (or test double) “when testing things that cross the dependency inversion boundaries of the system” (per Bob Martin). If I truly need a test double, I go to the highest level in the class hierarchy diagram above that will get the job done. In other words, don't use a mock if a spy will do.

Is Mockito a dependency injection?

Mockito tries to inject mocked dependencies using one of the three approaches, in the specified order. Constructor Based Injection - when there is a constructor defined for the class, Mockito tries to inject dependencies using the biggest constructor.

Can you only mock an interface?

Because of this, you can only mock interfaces, or virtual methods on concrete or abstract classes. Additionally, if you're mocking a concrete class, you almost always need to provide a parameterless constructor so that the mocking framework knows how to instantiate the class.


1 Answers

If you have a choice, you should almost always expose a constructor to allow dependencies to be injected. You could still keep the convenience constructor (though some would argue that you shouldn't):

public Brain() : this(new Hand(), new Mouth()) { }

That said, in addition to Isolator you could check out the latest builds of Pex (0.17), which include moles that provide a mechanism similar to Isolator's Swap.

like image 56
dahlbyk Avatar answered Oct 09 '22 21:10

dahlbyk