服务结构单元测试和依赖注入

时间:2015-11-15 21:43:28

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

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

据我所知,部署的SF Reliable Services / Actors不是标准的.NET类,部署的S / A的单元测试可能是一个奇怪的想法。

无论如何,我现在试着尝试一下。

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

这样做是不错的主意。也许有一些单元测试SF的指导原则?感谢。

更新

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

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

这是否意味着SF服务将改善其DI支持?演员怎么样?

2 个答案:

答案 0 :(得分:18)

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

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

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

编辑:更新了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模拟,您可以将其用作自己的单元测试的起点。

答案 1 :(得分:4)

为了嘲笑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