Faking all instances of every parent using Typemock

177 views Asked by At

I've recently started using Typemock and have looked through at least half a dozen existing threads, but can't seem to find an answer to my exact problem.

I have a class C that derives from B, that itself derives from A. The instance of C is what I need to test and therefore needs to be real. But as C derives from B (and indirectly A), I need those two classes completely faked automatically when I create an instance of C.

See below:

class A
{
    protected int methodA()
    {
        return 1;
    }
}

class B : A
{
    protected int methodB()
    {
        return 5;
    }
}

class C : B
{
    public int methodC()
    {
        return methodA() * methodB();
    }
}

class Test
{
    public Test()
    {
        A fake_A = Isolate.Fake.AllInstances<A>(Members.ReturnRecursiveFakes, ConstructorWillBe.Ignored);
        Isolate.NonPublic.WhenCalled(fake_A, "methodA").DoInstead((MethodCallContext ctx) =>
            {
                return 2;
            }
        );

        B fake_B = Isolate.Fake.AllInstances<B>(Members.ReturnRecursiveFakes, ConstructorWillBe.Ignored);
        Isolate.NonPublic.WhenCalled(fake_B, "methodB").DoInstead((MethodCallContext ctx) =>
            {
                return 10;
            }
        );

        C c = new C(); // Would expect A and B to be faked automatically since I've faked all instances above. 
        int method_c_val = c.methodC(); // I get back 5, but what I need returned is 20.
    }
}

This is an extremely simplified version of the problem I'm facing. It's not just a matter of faking behaviour of one or two methods in the parent classes. The entire parent heirarchy needs to be faked. So A and B both need to be faked completely, not partially.

One of the threads I've already looked at is this one, but the answer in there points to an address which is no longer available:

https://www.typemock.com/answers/11613/mocking-all-instances-of-a-base-class

2

There are 2 answers

2
Gregory Prescott On

As @Nkosi suggested you can use:

C c = Isolate.Fake.Instance<C>(Memebers.CallOriginal);
Isoalte.NonPublic.WhenCalled(c,"methodA").WillReturn(2);
Isoalte.NonPublic.WhenCalled(c,"methodB").WillReturn(10);

You fake the C object but it's methods still call the original implementation (If necessary), and you fake only the methods in question.

1
Nkosi On

I am not familiar with typemock, but if you are unable to get an answer, are in control of the code in question and able to modify it, I can suggest another possible workaround.

Make the methods in question virtual, giving the ability of derived classes to override them.

class A
{
    protected virtual int methodA()
    {
        return 1;
    }
}

class B : A
{
    protected virtual int methodB()
    {
        return 5;
    }
}

class C : B
{
    public int methodC()
    {
        return methodA() * methodB();
    }
}

To test methodC in isolation you can create a stub class D derived from C that overrides the methods in question.

class D : C
{
    protected override int methodA()
    {
        return 2;
    }

    protected override int methodB()
    {
        return 10;
    }
}

With that the test would perform just as expected.

[TestClass]
public class Test
{
    [TestMethod]
    public void TestMethodC()
    {
        //Arrange
        var expected = 20;
        var c = new D();

        //Act
        int actual = c.methodC();

        //Assert
        Assert.AreEqual(expected, actual);
    }
}

I would think that with typemock you would need to do something similar by faking C and only isolating the two dependency methods in question, leaving the method under test to be called naturally. But again I am not that familiar with that framework.