Moq with Unity Container unit testing
Asked Answered
G

2

5

below is an example of production code that I am trying to unit test. I am struggling to resolve a dependency to a concrete class that is being used.

public MyClass(IUnityContainer container)
{
    this.unityContainer = container;
}

public string DoWork()
{
     var sender = unityContainer.Resolve<IInterface>();  // how to setup this object
     var json = sender.Send("something");
     var value = serializer.Deserialize<SomeModel>(json);
     return value.url;
}

I want to mock out the IInterface used by this method. How do I set that up in my unit test code? I feel like there is something missing here. this has a smell of an anti-pattern.....

Gagliano answered 9/9, 2015 at 15:51 Comment(1)
@CodeCaster It isnt my code :( just simply trying to increase our code coverage. I have no idea why they are passing an instance of the DI container into this class.Gagliano
W
13

This is the "service locator" antipattern, where you inject your dependency injection container / inversion of control into your logic.

You should pass the IInterface that it depends on instead, so that you control what instances it can otain. See Dependency Injection container in constructor.

If you can't refactor the class, you have to injecting the container in your unit test. Set up the container to return an instance (or rather, a mock) of IInterface. Like this:

public void MyUnitTest()
{
    IUnityContainer myContainer = new UnityContainer();
    myContainer.RegisterType<IInterface, YourInstance>();

    MyClass classUnderTest = new MyClass(myContainer);
    classUnderTest.DoWork();
    
    Assert...
}

See How to use Unity.RegisterType with Moq? to mock the YourInstance.

Widen answered 9/9, 2015 at 15:57 Comment(0)
J
2

I agree with CodeCaster. The typical pattern would be to accept a parameter of type IInterface in the constructor and assign it to a class-level variable.

public MyClass(IInterface sender)
{
    this.sender = sender;
}

When testing, simply pass in your moq. That said, there are times when I dislike passing in a dependency through the constructor. Such as:

  • I may need multiple instances of a class
  • The object is only needed conditionally.
  • The class's constructor may depend on additional values that are not determined until run time.

In those cases, passing the container as a parameter is the only solution I've come across. Just be sure to register your initial instance of the container with itself. Otherwise, the DI will provide your constructor with a new (empty) container. If anyone has a better pattern, particularly one that works with Unity, I'd love to see it.

Jannet answered 20/6, 2018 at 14:36 Comment(1)
Another option for just-in-time or multiple instances is to pass in a factory interface. Then you call the factory zero or more times with on-the-fly parameters as needed (or not needed).Goddess

© 2022 - 2024 — McMap. All rights reserved.