1

I'm new to FakeItEasy, sorry if the solution is obvious.

This is the simplified code which reproduces the problem:

I have a base class:

public abstract class BaseClass
    {
        public void Do()
        {
            Do_Override();
        }

        protected abstract void Do_Override();
    }

and a derived one:

  public class ImplementingClass: BaseClass
    {
        protected override void Do_Override()
        {
            ProtectedDo();
        }

        protected virtual void ProtectedDo()
        {

        }        
    }

In my test I want to see if ProtectedDo() was called. I've tried to test in two ways, but tests are failing with the same message:

1st. In debug mode it is not entering in Do_Override()

 public class ImplementingClassShould
    {
        [Fact]
        public void Run_ProtectedDo()
        {
            var fake = A.Fake<ImplementingClass>();
            fake.Do();
            A.CallTo(fake).Where(_ => _.Method.Name == "ProtectedDo").MustHaveHappened();

        }
     }

2nd. In debug mode it is entering in Do_Override()

 public class ImplementingClassShould
    {    
        [Fact]
        public void Run_ProtectedDo_V2()
        {
            var sut = new ImplementingClass();
            var sutFakeWrapper = A.Fake<ImplementingClass>(_ => _.Wrapping(sut));
            sutFakeWrapper.Do();
            A.CallTo(sutFakeWrapper).Where(_ => _.Method.Name == "ProtectedDo").MustHaveHappened();

        }        
    }

Fail message:

enter image description here

cdi
  • 33
  • 5
  • Hi, @fmm. I like the simplified repro, but it's generally a good idea to indicate what went wrong in your experience. For example, why don't you think your code is working? – Blair Conrad Jun 30 '21 at 10:37
  • Hi, @BlairConrad. I've update my question with the message of test failing. Also my 2nd try to test. Thanks. – cdi Jun 30 '21 at 10:50

1 Answers1

1

Your test is perfectly good, as far as it goes. If you run it, it'll tell you that ProtectedDo was not called, which is accurate. Because Do_Override is virtual, FakeItEasy intercepts the call. (The protectedness doesn't affect things in this case.)

If you don't want Do_Override to be intercepted by FakeItEasy, you should configure the Fake to call the base method instead of handling the call itself:

[Fact]
public void Run_ProtectedDo()
{
    var fake = A.Fake<ImplementingClass>();

    A.CallTo(fake).Where(_ => _.Method.Name == "Do_Override").CallsBaseMethod();

    fake.Do();
    A.CallTo(fake).Where(_ => _.Method.Name == "ProtectedDo").MustHaveHappened();

}

Update in light of the newly added Run_ProtectedDo_V2 test:

I expect you know this already, @fmm, but the test still fails. This is because when sutFakeWrapper.Do is called, it forwards to the wrapped sut.Do. Since sut is a concrete ImplementingClass, it calls its Do_Override, which calls its ProtectedDo, so it's possible to debug into a ProtectedDo method call. Only it's sut.ProtectedDo, not sutFakeWrapper.ProtectedDo. Hence the test failure.

Blair Conrad
  • 233,004
  • 25
  • 132
  • 111