在已经实例化的具体类上模拟虚拟方法

时间:2020-01-14 06:23:17

标签: c# unit-testing mocking azure-service-fabric

我希望为Service Fabric参与者编写一些单元测试。指南here建议使用名为ServiceFabric.Mocks的NuGet程序包,该程序包简化了各种Service Fabric实体的模拟。

到目前为止,所有这些都是有意义的。我可以使用以下代码为演员提供具体的实现方式:

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;
}

只要我坚持打包文档中的示例并测试单个方法的结果,就可以开始工作了。但是,我有一个方法可以在actor中调用另一个方法并使用其结果。看起来如下:

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

    //...
  }

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

我希望能够在actor中模拟DoThat方法,因此我可以测试DoThis方法,但是由于ServiceFabric.Mocks的结果是一个具体的对象,因此尚不清楚如何执行该操作。

我认为前进的唯一两种方法是: 1)确定创建已实例化类的模拟的方法 2)自己重新创建该模拟库的功能,这样我就可以在创建具体对象之前模拟该方法

有没有办法不借助#2而接近#1?

1 个答案:

答案 0 :(得分:2)

您可以在单元测试附近创建一个新类,而不是使用模拟程序,该类继承自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;
}

或者,您可以将逻辑从DoThat移到带有接口的单独类中,使用依赖注入并为测试/实际运行传递不同的实现。