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

C# 服务结构单元测试和依赖注入,c#,web-services,unit-testing,azure,azure-service-fabric,C#,Web Services,Unit Testing,Azure,Azure Service Fabric,我不能仅仅通过调用一个可靠的服务/参与者的构造函数然后测试它的方法来测试它var testService=new SomeService()引发NullReferenceException。那么,如何使用已部署的服务 我知道部署的SF可靠服务/参与者不是标准的.NET类,对部署的S/A进行单元测试可能是一个奇怪的想法 不管怎么说,我现在正试着试试 比如说。我刚刚部署了一个服务,在测试中我创建了一个代理对象,并将项添加到服务的输入队列中。然后我需要断言输入队列计数=1。如果我刚刚部署了一个服务,而

我不能仅仅通过调用一个可靠的服务/参与者的构造函数然后测试它的方法来测试它<代码>var testService=new SomeService()引发NullReferenceException。那么,如何使用已部署的服务

我知道部署的SF可靠服务/参与者不是标准的.NET类,对部署的S/A进行单元测试可能是一个奇怪的想法

不管怎么说,我现在正试着试试

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

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

更新:

在调查过程中,我发现了以下待办事项字符串:

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

这是否意味着SF服务将改善其DI支持?参与者呢?

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

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

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

编辑:使用GA发布API(2.0.135)更新

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

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

  target.MyMethod();
  // validate results and all that good stuff
}
我们有一个实际服务的完整工作示例,其中许多依赖项在GitHub上进行了单元测试:


此示例还包含IReliableStateManager和iReliableSdictionary模拟,您可以将其用作自己单元测试的起点。

要在可靠的参与者中模拟状态管理器,可以执行以下操作:

实际上,
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;
    }
}

只需确保在代码的其余部分始终使用
\u stateManager
,而不是使用
这个。stateManager

谢谢,瓦茨拉夫!这正是我们所需要的。请查看更新。在RTM(Actors 2.0.135)中,
Actor.StateManager
属性是只读的(无
受保护集
)。我应该如何为我的actor类注入状态管理器依赖项?对于actor的提醒和计时器呢?我可以自己调用
receiverEminederAsync
方法,但我需要验证对
registerEminederAsync
(ActorBase上的受保护方法)的调用。似乎我们仍然不能像拉尔斯说的那样嘲笑州经理。有什么解决办法吗?如果我们真的看不到参与者对状态做了什么,我们如何对他们进行单元测试?@VaclavTurecek:你能提供一个例子,说明如何“注入你自己的状态管理接口来包装状态管理器”?构造函数依赖项注入现在实际上在参与者中可用!注册actor类型时,还可以注册一个“factory”,它实际上只是一个Func,您可以在其中创建actor类实例,从而控制actor的实例化,从而可以通过它注入依赖项。在“服务”中,您已经可以做到这一点,请查看我们在Party Cluster示例中是如何做到的:我写了一个关于使用unity进行依赖项注入的答案:@VaclavTurecek您的链接已断开
private readonly IActorStateManager _stateManager;

public MyActor(IActorStateManager stateManager = null)
{
    _stateManager = stateManager ?? this.StateManager;
}
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;
    }
}