Using IoC for Unit Testing
Asked Answered
C

4

97

How can a IoC Container be used for unit testing? Is it useful to manage mocks in a huge solution (50+ projects) using IoC? Any experiences? Any C# libraries that work well for using it in unit tests?

Colorful answered 23/9, 2009 at 13:2 Comment(2)
@Mark Seemann would be too humble to point it out, but if you're interested in this question, you should at least be aware of AutoFixtureHypsometry
There's a good talk about relationship between DI and mocking on Vimeo by Miguel Castro: vimeo.com/68390510Weathers
C
135

Generally speaking, a DI Container should not be necessary for unit testing because unit testing is all about separating responsibilities.

Consider a class that uses Constructor Injection

public MyClass(IMyDependency dep) { }

In your entire application, it may be that there's a huge dependency graph hidden behind IMyDependency, but in a unit test, you flatten it all down to a single Test Double.

You can use dynamic mocks like Moq or RhinoMocks to generate the Test Double, but it is not required.

var dep = new Mock<IMyDependency>().Object;
var sut = new MyClass(dep);

In some cases, an auto-mocking container can be nice to have, but you don't need to use the same DI Container that the production application uses.

Cheston answered 23/9, 2009 at 13:9 Comment(4)
agreed... unless a testing target has a IoC container as a dependency, your tests shouldn't need them... you are going to remove the majority of the object graph when you do your unit tests.Malcom
@Mark Seemann This makes sense... But what about integration tests? I.e., i played around with UI tests and i faced situation when i had to share composition root. Any comments?Trilbie
@Arnis L.: For integration tests it's less important. You can choose to use a DI Container to wire up the components, but if so, you are likely to need a different configuration for the container than in the full application - unless you perform a Subcutaneous Test or a full System Test, in which case you can reuse the application's configuration of the Container.Cheston
ref to msdn magazine Test Double: download.microsoft.com/download/3/A/7/…Maxwell
L
19

I often use an IoC container in my tests. Granted, they are not "unit tests" in the pure sense. IMO They are more BDDish and facilitate refactoring. Tests are there to give you confidence to refactor. Poorly written tests can be like pouring cement into your code.

Consider the following:

[TestFixture]
public class ImageGalleryFixture : ContainerWiredFixture
{
    [Test]
    public void Should_save_image()
    {
        container.ConfigureMockFor<IFileRepository>()
            .Setup(r => r.Create(It.IsAny<IFile>()))
            .Verifiable();

        AddToGallery(new RequestWithRealFile());

        container.VerifyMockFor<IFileRepository>();
    }

    private void AddToGallery(AddBusinessImage request)
    {
        container.Resolve<BusinessPublisher>().Consume(request);
    }
}

There are several things that happen when adding an image to the gallery. The image is resized, a thumbnail is generated, and the files are stored on AmazonS3. By using a container I can more easily isolate just the behavior I want to test, which in this case is the persisting part.

An auto-mocking container extension comes in handy when using this technique: http://www.agileatwork.com/auto-mocking-unity-container-extension/

Lykins answered 24/9, 2009 at 5:44 Comment(1)
+1 for the phrase "like pouring cement into your code". I've started using it all the time.Bertine
E
18

How can a Ioc Container be used for unit testing?

IoC will enforce programming paradigms that will make unit testing in isolation (i.e. using mocks) easier: use of interfaces, no new(), no singletons...

But using the IoC container for testing is not really a requirement, it will just provide some facilities e.g. injection of mocks but you could do it manually.

Is it useful to manage mocks in a huge solution (50+ projects) using IoC?

I'm not sure what you mean by managing mocks using IoC. Anyway, IoC containers can usually do more than just injecting mocks when it comes to testing. And if you have decent IDE support that makes refactoring possible, why not using it?

Any experience?

Yes, on a huge solution, you need more than ever a non error-prone and refactoring-adverse solution (i.e. either through a type safe IoC container or good IDE support).

Evangel answered 23/9, 2009 at 13:32 Comment(0)
V
2

Using containers with ability to resolve unregistered/uknown services like SimpleInjector, DryIoc (its mine) can return mocks for not yet implemented interfaces.

Which means that you can start development with first simple implementation and its mocked dependencies, and replace them with real thing as you progress.

Viewer answered 11/4, 2014 at 13:53 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.