Виртуальный виртуальный метод для уже созданного конкретного класса - PullRequest
1 голос
/ 14 января 2020

Я хочу написать несколько юнит-тестов для актеров Service Fabri c. Руководство здесь предлагает использовать пакет NuGet с именем ServiceFabri c .Mocks , который упрощает ускорение макетов различных объектов Service Fabri c.

Все это имеет смысл до сих пор. Я могу использовать следующее, чтобы ускорить конкретную реализацию для моего актера:

private MyActor CreateActor(ActorId id) 
{
  Func<ActorService, ActorId, ActorBase> factory = (service, actorId) => new MyActor(service, id);
  var svc = MockActorServiceFactory.CreateActorServiceForActor<MyActor>(factory);
  var actor = svc.Activate(id);

  return actor;
}

Пока я придерживаюсь примера в пакетной документации и проверяю результат одного метода, я настроен. Однако у меня есть метод, который вызывает другой метод в актере и использует его результат. Это выглядит следующим образом:

public class MyActor : Actor, IMyActor 
{
  public async Task<string> DoThis()
  {
    var result = await DoThat();

    //...
  }

  public virtual async Task<string> DoThat()
  {
     //...
  }
}

Я хотел бы иметь возможность смоделировать метод DoThat в моем актере, чтобы я мог проверить метод DoThis, но не ясно, как это сделать, учитывая, что результат ServiceFabri c .Mocks - это конкретный объект.

Я вижу только два пути продвижения вперед: 1) Определить способ создания макета уже созданного экземпляра класса. 2) Воссоздать функциональность этой библиотеки макетов самостоятельно, чтобы я мог смоделировать метод до того, как конкретный объект создан

Есть ли способ go приблизиться к # 1, не прибегая к # 2?

1 Ответ

2 голосов
/ 14 января 2020

Вместо использования макета, вы можете создать новый класс рядом с вашим модульным тестом, который будет наследоваться от вашего MyActor и переопределить реализацию DoThat для целей тестирования:

private class MyTestActor : MyActor
{
   public string Result {get; set;} = "ok";
   public override Task<string> DoThat() { return Task.FromResult(Result); }
}

Ваш тест код будет выглядеть следующим образом:

private MyActor CreateActor(ActorId id) 
{
  Func<ActorService, ActorId, ActorBase> factory = (service, actorId) => new MyTestActor(service, id);
  var svc = MockActorServiceFactory.CreateActorServiceForActor<MyTestActor>(factory);
  var actor = svc.Activate(id);

  return actor;
}

Или вы можете переместить логи c из DoThat в отдельный класс с интерфейсом, использовать внедрение зависимостей и передавать различные реализации для тестовых / реальных прогонов .

...