1

I'm dealing with a brownfield app. Due to high complexity and no existing tests, dependency injection is not an option at this point. This code also does not program to interfaces. So any solution I come up with has to not use DI or interfaces.

I'm looking at fakeiteasy to see if it can provide us with some test capabilities that do not require major refactoring efforts. I'm also considering Microsoft Fakes if I can manage to get a license for it.

Specifically, I want to know if I can override a base class implementation while also testing the derived class:

[TestMethod]
public void Test()
{
    //I want SomeBase to be fully mocked.  
    var baseFake = A.Fake<SomeBase>();

    //Class under test.  Create wrapper - unconfigured calls will be forwarded to wrapped
    SomeDerived someDerived = new SomeDerived();
    var derivedFakeWrapper = A.Fake<SomeDerived>(x => x.Wrapping(someDerived));

    A.CallTo(() => derivedFakeWrapper.OtherCall()).DoesNothing();
    //A.CallTo(() => derivedFakeWrapper.SomeCall()).DoesNothing();//This works.  But I want to test SomeCall()
    A.CallTo((() => derivedFakeWrapper.DoWork())).DoesNothing();//SomeCall makes a call to DoWork().  DoWork() should do nothing
    A.CallTo((() => baseFake.DoWork())).DoesNothing();//Tried sticking somethin in the base

    derivedFakeWrapper.SomeCall();
    derivedFakeWrapper.OtherCall();
}

public class SomeBase
{
    public virtual void DoWork()
    {
        Console.WriteLine("base implementation");
    }
}

public class SomeDerived : SomeBase
{
    public virtual void SomeCall()
    {
        Console.WriteLine("Do other work");
        DoWork();
    }

    public virtual void OtherCall()
    {
        Console.WriteLine("Other call working normally");
    }
}
P.Brian.Mackey
  • 43,228
  • 68
  • 238
  • 348

1 Answers1

1

I would not introduce a wrapper here. I think it just adds complexity for no benefit. (Of course, I'd prefer not to test like this at all, but given the constraints you've laid out, I agree: there's not much else you can do.)

Instead, I'd fake the class under test with a directive to forward all calls to the original implementation. Then configure DoWork to do nothing:

[Test]
public void Test()
{
    // Class under test. Unconfigured calls will use actual implementation
    var fakeDerived = A.Fake<SomeDerived>(x => x.CallsBaseMethods());
    A.CallTo(() => fakeDerived.DoWork()).DoesNothing();

    A.CallTo(() => fakeDerived.OtherCall()).DoesNothing();

    fakeDerived.SomeCall();
    fakeDerived.OtherCall();
}
Blair Conrad
  • 233,004
  • 25
  • 132
  • 111