Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Moq with Unity Container unit testing

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.....

like image 302
Mateo Avatar asked Dec 11 '22 21:12

Mateo


2 Answers

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.

like image 142
CodeCaster Avatar answered Dec 13 '22 10:12

CodeCaster


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.

like image 36
Jack Whipnert Avatar answered Dec 13 '22 09:12

Jack Whipnert