【问题标题】:Mocking virtual method on already-instantiated concrete class在已经实例化的具体类上模拟虚拟方法
【发布时间】:2020-04-30 20:47:05
【问题描述】:

我希望为 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?

【问题讨论】:

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


    【解决方案1】:

    您可以在单元测试附近创建一个新类,而不是使用模拟,该类继承自您的 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 移动到具有接口的单独类中,使用依赖注入并传入不同的实现以进行测试/实际运行。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-12-22
      • 1970-01-01
      • 2013-03-08
      • 2011-09-30
      • 1970-01-01
      • 2011-06-29
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多