2

I'm new to using Moq with Xunit in Visual Studio 2019.

I want to mock the contructor call of a class that is being called in the contructor of my tested class. A simple demonstration of my problem:

public class MockedClass : IMockedClass
{
   public MockedClass()
   {
      // don't call this
   }
   public List<string> Function1()
   { /* return a List<string> here */ }
}
public class MyClass
{
   readonly IMockedClass mockedClass = null;
   public MyClass()
   {
      mockedClass = new MockedClass();
   }
   public string Function2()
   { /* return a string here */ }
}
public class MyClassTest
{
   [Fact]
   public string Function2Test()
   {
      var returnMock = new List<string>() { "1", "2", "3" };
      var mockMockedClass = new Mock<IMockedClass>();
      mockMockedClass.Setup(x => x.Function1()).Returns(returnMock);
      var myClass = new MyClass();
      var result = myClass.Function2();
      ...
   }
}

My problem is, that in the test Function2Test the constructor of MyClass is being called that calls the constructor of MockedClass. But I don't want the constructor of MockedClass being called.

How can I mock the constructor of MockedClass?

user3079834
  • 2,009
  • 2
  • 31
  • 63
  • 2
    Does this answer your question? [How to unit test a method or constructor which creates a new instance of another class](https://stackoverflow.com/questions/29754880/how-to-unit-test-a-method-or-constructor-which-creates-a-new-instance-of-another) – devNull Feb 15 '20 at 17:09

2 Answers2

3

I think you might need to slightly modify your code. You see, obtaining a mock of an interface by itself does not automatically change how other implementations behave when instantiated from other parts of code. You generally want to inject your mocked implementations into tested code via Dependency Injection.

public class MyClass
{
    readonly IMockedClass mockedClass = null;
    public MyClass(IMockedClass c)
    {
        mockedClass = c; // now you'll get the correct implemetation
    }
    public string Function2()
    { /* return a string here */ }
}
void Main()
{

        var returnMock = new List<string>() { "1", "2", "3" };
        var mockMockedClass = new Mock<IMockedClass>(); // get your mock here
        mockMockedClass.Setup(x => x.Function1()).Returns(returnMock);
        var myClass = new MyClass(mockMockedClass.Object); // inject it here
        var result = myClass.Function2();
}

Then you will need to set up your Dependency Injection container to provide you with a concrete MockedClass when your actual application code runs. Depending on your code and requirements, there are heaps of options so I won't recommend a specific framework here.

Theoretically, you might be able to mock out the class in your current code structure. I could potentially see how you either opt for Fakes or fancy reflection techniques. However it likely will be way to much effort for going against what seems to be community-accepted best practice.

timur
  • 14,239
  • 2
  • 11
  • 32
1

You were on the right direction to mock dependencies, but you lack the implementation of the Dependency Inversion Principle.

With your code as-is, you are tying your MyClass to the MockedClass, and furthermore you let MyClass control the MockedClass object's lifetime.

What you should do, is alter the constructor of MyClass to accept an IMockedClass object. Note that you should pass the interface, not the class type.

public class MyClass
{
   readonly IMockedClass mockedClass = null;
   public MyClass(IMockedClass mockedClass)
   {
      this.mockedClass = mockedClass();
   }
   public string Function2()
   { /* return a string here */ }
}

and your test code will be:

public string Function2Test()
   {
      var returnMock = new List<string>() { "1", "2", "3" };
      var mockMockedClass = new Mock<IMockedClass>();
      mockMockedClass.Setup(x => x.Function1()).Returns(returnMock);
      var myClass = new MyClass(mockMockedClass.Object);
      var result = myClass.Function2();
      ...
   }
Sotiris Panopoulos
  • 1,523
  • 1
  • 13
  • 18