Xander
Xander

Reputation: 9171

Unit testing with ServiceLocator

I am doing a unit test on a class that uses the unity dependency injection framework.

This returns null: ServiceLocator.Current.GetInstance();

How can I get it to return a mock object or just the object itself?

Upvotes: 6

Views: 8848

Answers (4)

Wim Coenen
Wim Coenen

Reputation: 66743

MSDN has this example that shows how to implement the service locator pattern with Unity. Essentially, you should pass the service locator object as a constructor argument of your class. This enables you to pass a MockUnityResolver, allowing you to take full control in a unit test.

[TestMethod]
public void InitCallsRunOnNewsController()
{
    MockUnityResolver container = new MockUnityResolver();
    var controller = new MockNewsController();
    container.Bag.Add(typeof(INewsController), controller);
    var newsModule = new NewsModule(container);

    newsModule.Initialize();

    Assert.IsTrue(controller.RunCalled);
}

Upvotes: 4

quetzalcoatl
quetzalcoatl

Reputation: 33546

You can always setup a Container+ServiceLocator and actually fulfill the required dependencies, for example, by registering mocks. See code examples #4 for how to setup a container/locator:

http://blogs.msdn.com/b/miah/archive/2009/05/12/servicelocator-and-unity-be-careful.aspx

Upvotes: 1

Grant Palin
Grant Palin

Reputation: 4558

You could make use of Poor Man's injection. Create a default constructor which retrieves the dependencies from the service locator, and forward those dependencies to a "real" constructor which takes them as parameters. That takes care of production situations.

Then when testing the class in question, pass in a fake/mock version of the dependencies to the "real" constructor, bypassing the default one altogether.

Upvotes: 5

Pete
Pete

Reputation: 11495

Are you testing your core "DI integration" code? If not, your normal code should never (well, rarely) be interacting with your DI framework.

Normally your dependencies will be injected via constructor injection, and when testing, you can instead supply mock objects as those constructor dependencies. For example:

public class Foo {
    public Foo (IBar bar) {
        bar.Lift ();
    }
}

With the above code, you can simply mock IBar, and pass it to the Foo constructor.

Upvotes: 1

Related Questions