Как обернуть экземпляр, но при этом переадресовывать вызовы обернутым членам экземпляра?

#fakeiteasy

#fakeiteasy

Вопрос:

Учитывая, что у меня есть такой обернутый экземпляр, где метод Resolve вводит зависимости

     var handler = this.Resolve<DeletePaymentCardHandler>();

    var wrapperHandler = A.Fake<DeletePaymentCardHandler>(
        o => o.Wrapping(handler));
    
    A.CallTo(() => wrapperHandler.EnsurePaymentCardCanBeDeleted(A<DeletePaymentCard>._, A<CancellationToken>._ ))
     .Returns(Task.CompletedTask);
    
    await wrapperHandler.Handle(command, CancellationToken.None);
 

Где метод ‘Handle’ реализован следующим образом

 public async Task Handle(DeletePaymentCard msg, CancellationToken cancellationToken)
{
     await this.EnsurePaymentCardCanBeDeleted(msg, cancellationToken);

     var instance = await this.repository.GetById<Domain.CustomerFundingSources>(msg.CustomerId, cancellationToken);

     instance.Process(msg);

     await this.repository.Save(instance);
}

public virtual async Task EnsurePaymentCardCanBeDeleted(DeletePaymentCard command, CancellationToken cancellationToken)
{
    return Task.CompletedTask
}
 

Я наблюдаю, что вместо этого вызова в дескрипторе, вызывающем внедренный репозиторий, он вызывает прокси, созданный FakeItEasy?

 var instance = await this.repository.GetById<Domain.CustomerFundingSources>(msg.CustomerId, cancellationToken);
 

Я думал, что смысл в том, чтобы иметь возможность перехватывать только вызовы некоторых методов, а rest должен вызывать обернутые методы экземпляра?
Из документации:

«По умолчанию вызовы для обертывания подделки, которые не были явно настроены, будут перенаправлены на обернутый объект».

Ответ №1:

Невозможно быть полностью уверенным без доступа ко всему коду DeletePaymentCardHandler , но вот как это выглядит для меня:

Handle не является виртуальным, поэтому будет выполняться код внутри DeletePaymentCardHandler , полностью обходя FakeItEasy.

В Handle , GetById метод вызывается для repository поля (доступ repository не является вызовом метода, и FakeItEasy не может перехватить доступ к полю), который, скорее всего, был инициализирован конструктором поддельного DeletePaymentCardHandler класса.

Если repository поле инициализируется из аргумента конструктора, FakeItEasy предоставит фиктивный репозиторий для удовлетворения этого аргумента конструктора. Тип репозитория, скорее всего, является чем-то, что FakeItEasy может подделать, поэтому значение будет поддельным.

wrappedHandler.Handle Таким образом, в реальном Handle коде вызывается подделка repository .

Если вам нужно какое-то другое поведение, то, возможно, подделке необходимо предоставить тот же репозиторий, что и обработчик обернутого экземпляра. Или Handle можно получить доступ к репозиторию через виртуальное свойство или метод, который будет перехвачен FakeItEasy и перенаправлен обработчику wrapped, который затем получит доступ к репозиторию, предоставленному Resolve методом.