服务结构unit testing和dependency injection

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

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

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

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

这样做是不是一个坏主意。 也许有一些unit testingSF的指导方针? 谢谢。

更新:

在研究Service Fabric Web Reference Application示例时,我发现了这个TODO字符串:

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

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

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

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

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

编辑:更新了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上进行unit testing: https : //github.com/Azure-Samples/service-fabric-dotnet-management-party-cluster

此示例还具有IReliableStateManager和IReliableDictionary模拟,您可以将其用作自己的unit testing的起点。

为了在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