Wyatt
Wyatt

Reputation: 23

Mock a Class in a Class in a Unit Test

I have the following code in a unit test

using Moq;
using OtherClass;
[TestClass]
public class TestClass
{
    [TestMethod]
    public void TestMethod()
    {
        OtherClass other = new OtherClass();
        OtherClass.foo();
    }
}

Here is the other class

using ThirdClass;
public class OtherClass
{
    public void foo()
    {
        ThirdClass third = new ThirdClass();
        third.bar();
    }
}

ThirdClass is still under development, but I want to be able to run my unit tests using moq. Is there a way to tell moq to mock ThirdClass inside TestClass without having OtherClass use/depend on moq? Ideally something like:

public void TestMethod()
{
    OtherClass other = new OtherClass();
    Mock<ThirdClass> third =  new Mock<ThirdClass>();
    third.setup(o => o.bar()).Returns(/*mock implementation*/);
    /*use third in all instances of ThirdClass in OtherClass*/
    OtherClass.foo();
}

Upvotes: 2

Views: 21068

Answers (2)

Wyatt
Wyatt

Reputation: 23

Thanks for the ideas, guys. I ended up making another version of OtherClass.foo() that takes in an instance of ThirdClass, and in the version without it creates an instance. When testing I can call foo(mockThird), but users can just use foo().

using ThirdClass;
public class OtherClass
{
    public void foo(ThirdClass third)
    {
        third.bar();
    }
    public void foo()
    {
        foo(new ThirdClass());
    }
}

In the test class

public void TestMethod()
{
    Mock<ThirdClass> third =  new Mock<ThirdClass>();
    third.setup(o => o.bar()).Returns(/*mock implementation*/);
    OtherClass testObject= new OtherClass();

    testObject.foo(third);
}

Upvotes: 0

kat1330
kat1330

Reputation: 5322

Method foo() in class OtherClass is not unit testable because you creating new instance of real service and you cannot mock it.

If you want to mock it then you have to inject ThirdClass with dependency injection.

Example of OtherClass will be:

public class OtherClass
{
    private readonly ThirdClass _thirdClass;
    public OtherClass(ThirdClass thirdClass) 
    {
         _thirdClass = thirdClass;
    }
    public void foo()
    {
        _thirdClass.bar();
    }
}

Your test method with example of testing other class can be:

public void TestMethod()
{
    // Arrange
    Mock<ThirdClass> third =  new Mock<ThirdClass>();
    third.setup(o => o.bar()).Returns(/*mock implementation*/);

    OtherClass testObject= new OtherClass(third);

    // Action
    testObject.foo();

    // Assert
    ///TODO: Add some assertion.
}

You can use example try with Unity DI container.

Upvotes: 3

Related Questions