【问题标题】:Service Fabric Unit Testing and Dependency InjectionService Fabric 单元测试和依赖注入
【发布时间】:2016-02-16 23:10:28
【问题描述】:

我无法通过调用 Reliable Service/Actor 的构造函数然后测试它的方法来测试它。 var testService = new SomeService(); 抛出 NullReferenceException。那么我可以用已部署的服务做什么..

我了解已部署的 SF Reliable Services/Actor 不是标准的 .NET 类,对已部署的 S/A 进行单元测试可能是一个奇怪的想法。

不管怎样,我现在正在尝试一下。

例如。我刚刚部署了一个服务,而不是在测试中我创建了一个代理对象并将项目添加到服务的输入队列中。然后我需要断言输入队列计数 = 1。如果我刚刚部署了一个服务并且没有其他客户端/服务/参与者使用它的输入队列,它就可以工作。但是下一次这个测试将失败,这就是问题所在。我需要让服务停止与其他消费者一起操作,放下它的队列,然后测试它。为此,我可以创建一些 TestMode 属性和 PropareoForTests/TestingCompleted 等方法,并在测试前后从测试客户端调用它们。

这样做是不是一个坏主意。也许有一些关于单元测试 SF 的指南?谢谢。

更新:

在调查 Service Fabric Web Reference Application example 时,我发现了这个 TODO 字符串:

/// TODO: Temporary property-injection for an IServiceProxyWrapper until constructor injection is available.

这是否意味着顺丰服务将改进其 DI 支持?演员呢?

【问题讨论】:

  • 构造函数依赖注入实际上现在可以在actor中使用!当您注册您的演员类型时,您还可以注册一个“工厂”,它实际上只是一个 Func,您可以在其中创建您的 Actor 类实例,它使您可以控制您的 Actor 的实例化,以便您可以通过那里注入依赖项。在服务中你已经可以做到这一点,看看我们在派对集群示例中是如何做到的:github.com/Azure-Samples/…
  • 我写了一个关于用unity进行依赖注入的答案:stackoverflow.com/questions/30384780/…
  • @VaclavTurecek 您的链接已损坏

标签: c# web-services unit-testing azure azure-service-fabric


【解决方案1】:

实际上,您可以像测试 .NET 中的任何其他类一样测试 Reliable Services 和 Actors!它们的特殊之处仅在于它们在底层平台中使用了某些挂钩,但除此之外,您可以正常实例化您的服务或参与者类并在其上调用方法。

目前,Reliable Services 更容易进行单元测试,因为进入平台的主要挂钩状态管理器是一个可通过构造函数插入的接口。

例如,您的服务类可能如下所示:

编辑:更新为 GA 版本 API (2.0.135)

class MyService : StatefulService
{
  public MyService (StatefulServiceContext context, IReliableStateManager stateManager)
      :base (context, stateManager)
  {
  }

  public void MyMethod()
  {
    // do stuff..
  }
}

然后你可以像这样测试你的服务类:

[TestMethod]
public TestMyMethod()
{
  MockReliableStateManager stateManager = new MockReliableStateManager();
  MyService target = new MyService(stateManager);

  target.MyMethod();
  // validate results and all that good stuff
}

我们在 GitHub 上有一个完整的实际服务示例,其中包含许多正在单元测试的依赖项:https://github.com/Azure-Samples/service-fabric-dotnet-management-party-cluster

此示例还具有 IReliableStateManager 和 IReliableDictionary 模拟,您可以将它们用作您自己的单元测试的起点。

【讨论】:

  • 谢谢,瓦茨拉夫!这正是需要的。请查看更新。
  • 在 RTM(Actors 2.0.135)中,Actor.StateManager 属性是只读的(没有 protected set)。我应该如何为我的 actor 类注入状态管理器依赖项?
  • 演员的提醒和计时器呢?我可以自己调用ReceiveReminderAsync 方法,但我需要验证对RegisterReminderAsync 的调用(ActorBase 上的受保护方法)。
  • 看来我们仍然不能像 Lars 所说的那样嘲笑 state manager。有什么解决方案吗?如果我们不能真正看到他们对状态做了什么,我们如何对我们的演员进行单元测试?
  • @VaclavTurecek:您能否提供一个示例来说明如何“注入您自己的状态管理接口来包装状态管理器”?
【解决方案2】:

要在 Reliable Actors 中模拟状态管理器,您可以执行以下操作:

罢工>

private readonly IActorStateManager _stateManager;

public MyActor(IActorStateManager stateManager = null)
{
    _stateManager = stateManager ?? this.StateManager;
}

实际上,此时StateManager 尚未初始化。我们可以在调用OnActivateAsync 时得到它:

private IActorStateManager _stateManager;

// Unit tests can inject mock here.
public MyActor(IActorStateManager stateManager = null)
{
    _stateManager = stateManager;
}

protected override async Task OnActivateAsync()
{
    if (_stateManager == null)
    {
        _stateManager = StateManager;
    }
}

请确保在其余代码中始终使用_stateManager,而不是this.StateManager

【讨论】:

    猜你喜欢
    • 2017-02-05
    • 2018-03-03
    • 2021-06-19
    • 1970-01-01
    • 2017-11-03
    • 2010-10-23
    • 2017-04-01
    相关资源
    最近更新 更多