FakeItEasy — я не вижу, был ли вызван защищенный метод, когда метод вызывающего абонента переопределен

#unit-testing #fakeiteasy

Вопрос:

Я новичок в FakeItEasy, извините, если решение очевидно.

Это упрощенный код, который воспроизводит проблему:

У меня есть базовый класс:

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

        protected abstract void Do_Override();
    }
 

и производный:

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

        protected virtual void ProtectedDo()
        {

        }        
    }
 

В своем тесте я хочу посмотреть, был ли ProtectedDo() вызван. Я пытался протестировать двумя способами, но тесты проваливаются с одним и тем же сообщением:

1-й. В режиме отладки он не входит в 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();

        }
     }
 

2-е место. В режиме отладки он входит в 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();

        }        
    }
 

Сообщение об ошибке:

введите описание изображения здесь

Комментарии:

1. Привет, @fmm. Мне нравится упрощенное повторение, но, как правило, неплохо указать, что пошло не так в вашем опыте. Например, почему вы не думаете, что ваш код работает?

2. Привет, @BlairConrad. Я обновил свой вопрос сообщением о провале теста. Также моя 2-я попытка проверить. Спасибо.

Ответ №1:

Ваш тест совершенно хорош, насколько это возможно. Если вы запустите его, он сообщит вам, что ProtectedDo это не было вызвано, что является точным. Поскольку Do_Override это виртуально, FakeItEasy перехватывает вызов. (Защищенность в данном случае не влияет на вещи.)

Если вы не хотите Do_Override , чтобы вас перехватил FakeItEasy, вам следует настроить подделку для вызова базового метода вместо обработки самого вызова:

 [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();

}
 

Обновление в свете недавно добавленного Run_ProtectedDo_V2 теста:

Я ожидаю, что вы уже знаете это, @fmm, но тест все равно проваливается. Это происходит потому, что, когда sutFakeWrapper.Do вызывается, он перенаправляется на завернутый sut.Do . Поскольку sut это конкретный ImplementingClass , он вызывает свой Do_Override , который вызывает свой ProtectedDo , поэтому его можно отлаживать в ProtectedDo вызов метода. Только это sut.ProtectedDo не sutFakeWrapper.ProtectedDo так . Отсюда и провал теста.