Combination of unit tests (bullying) and Dependecy Injection development system

Possible duplicate:
Using IoC for Unit Testing

I think I have a problem understanding how Unit tests and / or Dependency Injection tests work. I use NUnit and Rhino Mocks for unit testing and Ninject as an Injection Dependency platform. In general, I, although these two will come to perfection, but for some reason it seems that it is becoming more complex and difficult to understand.

(I will try to make a good example so that it is clean and easy. It's about me, cycling).

1.) Without DI / Unit tests:
Unaware of the DI and Unit Tests, my code would look like this - and I would be happy:

public class Person { public void Travel() { Bike bike = new Bike(); bike.Ride(); } } public class Bike { public void Ride() { Console.WriteLine("Riding a Bike"); } } 

To ride my bike, I just need: new Person().Travel();

2.) With DI:
I don't want this hard link, so I need an interface and a NinjectModule! I would have a bit of Overhead, but it would be nice if the code is easy to read and understand. I just pass the code for the modified Person class, the Bike class will not change:

 public class Person { IKernel kernel = new StandardKernel(new TransportationModule()); public void Travel() { ITransportation transportation = kernel.Get<ITransportation>(); transportation.Ride(); } } 

I could still ride my bike with: new Person().Travel();

3.) Consideration of Unit-Testing (without DI):
To check if the Ride-Method is called correctly, I will need a Mock. As far as I know, there are two ways to introduce an interface: constructor injection and setter injector. I choose Constructor Injection for my example:

 public class Person { ITransportation transportation; public person(ITransportation transportation) { this.transportation = transportation; } public void Travel() { transportation.Ride(); } } 

This time I would ask to go through the bike: new Person(new Bike()).Travel();

4.) With DI and Unit-Tests preparation
A class in 3. Considering Unit-Testing (without DI) would do the job unchanged, but I would need to call new Person(kernel.Get<ITransportation>()); . Thanks to this, I feel that I am losing the benefit of DI - the Person class could call Travel without any connection and any need to know which class the transport is. In addition, I think that this form lacks the readability of Example 2.

Is this how it is done? Or are there other - more elegant ways to achieve Injection Dependency and the ability to unit test (and mock)?

(Looking back, it seems that the example is really bad - everyone should know which transport device he is traveling at the moment ...)

+7
source share
3 answers

As a rule, I try to avoid using the IoC container for my unit testing - just use mocks and stubs to pass dependencies.

Your problem starts in scenario 2: this is not a DI - it is a service locator (anti-) pattern . For real dependency injection, you need to pass your dependencies, preferably using constructor injection.

Scenario 3 looks good, it is a DI and, as a rule, also, as you can test your classes in isolation - pass the dependencies you need. I rarely find it necessary to use a full DI container for unit testing, since each tested class will have several dependencies, each of which can either be tricked or ridiculed to run the test.

I would even argue that if you need an IoC container, your tests are probably not small enough or you have too many dependencies. In a later case, there may be refactoring to form aggregate classes of two or more dependencies that you use (only if there is a semantic connection, of course). This ultimately reduces the number of dependencies to a level that is convenient for you. This maximum number for each person is different, I personally try to have a maximum of 4, at least I can count them on the one hand, and the mockery is not too much of a burden.

The final and decisive argument against using an IoC container in unit testing is behavioral testing . How can you be sure that the tested class behaves the way you want, if you are not in full control of your dependencies?

Perhaps you can achieve this by filling out all the dependencies using types that set flags for certain actions, but this is a big effort. It is much easier to use a mocking structure such as RhinoMocks or Moq to make sure certain methods have been called with the arguments you specify. To do this, you need to make fun of the dependencies you want to test, the IoC box cannot help you here.

+11
source

You confuse some things.

Implementation 3 is better than number 2 because you do not need to customize the DI structure in your unit tests.

So, when testing number 3 you will do:

 ITransportation transportationMock = MockRepository.GenerateStricktMock<ITransportation>(); // setup exceptations on your mock var person = new Person(transportationMock); 

The DI frame is what is needed only when building object trees in production code. In your test code, you have complete control over what you want to test. When the Unit Testing class, you mock all the dependencies.

If you also want to conduct integration testing, you will pass the real bike to your class and test it.

The idea of ​​testing classes in complete isolation is that you can control every code path. You can force the dependent to return correct or incorrect values, or you can even make this exception. If everything works, and you only have good code coverage from your unit tests, you will need only a few larger tests to make sure your DI is connected correctly.

The key to writing test code is to separate the creation of objects with business logic.

+4
source

My 2 cents ...

Although point 2 is an example of the Dependency Inversion Principle (DIP), it uses a service location pattern rather than dependency injection.

Your point 3 illustrates dependency injection where the IoC container injects the dependency (ITransportation) into the constructor during the creation of Person.

In your real application and unit test, you would like to use the IoC container to create Person (as well as not for the new Person). Either use the service locator pattern ( kernel.Get<Person>(); ), or DI (e.g. Setter) if this supports the Unit Test Framework.

This would create “Create a personality and its dependencies” (for example, “Customized specific class for IT transport”) and “Paste” in “Person” (it is obvious that in Unit Test your IoC will be configured for bullying / broken IT transport)

Finally, these are the Dependencies that you would like to execute Mock, i.e. ITransportation so you can test the Transport () Person method.

Since Bike has no dependencies, it can be Unit Tested directly / independently (you do not need a layout for testing Bike.Ride () if no dependency is added to the bike).

+3
source

All Articles