Understanding why we use Inversion of control containers for unit testing
I'm currently looking into incorporating Ninject into my unit tests. In going through some very intelligent posts related to earlier questions ( What is Ninject and when do you use it? , http://martinfowler.com/articles/injection.html ); I think I get some of the core concepts but I'm struggling with some if its applications.
Most times when IOC containters are brought up, its in relation to incorporating them into your unit tests. However, from a practical standpoint, does it make sense to use a framework like Ninject in my unit tests, if I have not yet incorporated it into my actual code base?
Case in point the example below (lifted from James Bender's Professional Test Driven Development with C#: Developing Real World Applications with TDD)
[TestFixture]
public class PersonServiceTests
{
[Test]
public void ShouldBeAbleToCallPersonServiceAndGetPerson()
{
var expected = new Person {Id = 1, FirstName = “John”, LastName = “Doe”};
var kernel = new StandardKernel(new CoreModule());
var personService = kernel.Get < PersonService > ();
var actual = personService.GetPerson(expected.Id);
Assert.AreEqual(expected.Id, actual.Id);
Assert.AreEqual(expected.FirstName, actual.FirstName);
Assert.AreEqual(expected.LastName, actual.LastName);
}
}
How does the writing my test using Ninject improve my life (or any poor developer who inherits my code) as oppose to just writing my test as:
[TestFixture]
public class PersonServiceTests
{
[Test]
public void ShouldBeAbleToCallPersonServiceAndGetPerson()
{
var expected = new Person {Id = 1, FirstName = “John”, LastName = “Doe”};
var personService = new PersonService();
var actual = personService.GetPerson(expected.Id);
Assert.AreEqual(expected.Id, actual.Id);
Assert.AreEqual(expected.FirstName, actual.FirstName);
Assert.AreEqual(expected.LastName, actual.LastName);
}
}
As I incorporate Dependency Inversion principles into my code; I see the value of IOC Containers as a way to reduce redundant/centralize code relating to how my classes are instantiated (as a result of respecting Dependency Inversion Principles). However, if I don't bother to use an IOC Container in my code, is it practical to use something like Ninject solely as part of my unit testing framework stack?
Why would you want to use a DI framework in your tests? Are your object graphs that difficult to compose?
Personally I think you would be better just making the tests create their dependencies explicitly as then injecting mocks or stubs will be explicit in the tests and very visible.
It also hides any issues around creating complex dependency hierarchies. Creating all the objects in the tests means you would have to feel the pain of creating those dependencies and might motivate you to improve the design.
I don't think that using a DI framework buys you anything in this situation, other than obfuscating the dependencies that your test has.
Integration tests might be a different story, but for unit tests...