我想在服务架构中对无状态服务进行集成.请帮我解决这个问题.我创建了像c#web api这样的无状态服务.
为了对您的可靠服务执行集成测试,您需要模拟和处理许多依赖项.您将无法以这种方式测试服务的所有情况或行为,FabricRuntime
主机和运行服务的方式难以复制(无需编写自己的FabricRuntime等效项).值得注意的是,没有FabricRuntime
集群(包括本地开发集群)也无法运行.
您还需要考虑集成测试的高级程度.例如,您的服务是否使用要在集成测试中包含的结构传输(默认通信模型)调用同一集群中的其他服务(包括演员)?您是否需要确保在同一服务分区的多次激活中持久保存状态?
首先,您需要摆脱所有硬依赖FabricRuntime
(对于依赖于它的东西)以及代码中的静态支持类:
服务/演员代理
ServiceProxy.Create<..)(..)>
调用其他服务时不要使用静态,而是确保您的服务接受IServiceProxyFactory
构造函数中的实例,并使用该实例创建服务调用服务的代理.同样的ActorProxy.Create<..>(..)
,用一个实例替换它IActorProxyFactory
.在program.cs
构建服务的位置,为服务new ServiceProxyFactory()
和服务方法执行某些功能.请注意创建此静态,但如果要在测试运行器中运行它,则不希望在同一容器中混合使用不同的测试.new ActorProxyFactory()
.这是最简单的部分,现在您需要模拟这些,以便您的集成测试实际上可以为下游服务创建某种形式的代理.您还需要创建某种形式的容器(如模拟FabricRuntime),它包含被调用服务和actor的实例.如果你不想测试它也会变得棘手RunAsync
服务背景
你需要嘲笑你的StatefulServiceContext
井以及如何创建你的服务.您的服务构造函数需要接受一个StatefulServiceContext
传递给基类的实例,因此您可以在创建服务时自由地提供您自己的模拟上下文实例.
public StatefulService(StatefulServiceContext serviceContext) : base(serviceContext) {}
服务设置和激活上下文
您还需要查看您的服务实现是否尝试读取ICodePackageActivationContext
服务清单中的任何设置(如此答案中所示)您在哪里设置和访问服务结构的每个环境的运行时配置参数?).在这种情况下,您需要将其替换为您自己的可模拟版本,并且您还需要在构造函数中注入它.您在大多数示例中找到的是对服务上下文的调用,如下所示:
this.Context.CodePackageActivationContext.GetConfigurationPackageObject("Config");
如果你在服务中这样做,那么你需要确保你也有一个模拟StatefulServiceContext
以及你的服务是如何创建的.当您使用运行时注册服务时,Program.Main()
您将获得StatefulServiceContext
注册调用中的实例:
ServiceRuntime.RegisterServiceAsync("ServiceType", context => new Service(context)).GetAwaiter().GetResult();
州
为了模拟状态并使其行为类似于在真实集群中运行时的行为,您需要模拟可靠状态的底层处理程序:IReliableStateManagerReplica
并且您需要将重载的构造函数添加到接受其实例的服务中.将它发送到基地:
public StatefulService(StatefulServiceContext serviceContext, IReliableStateManagerReplica reliableStateManagerReplica) : base(serviceContext, reliableStateManagerReplica) {}
对于actor IActorStateProvider
,如果要在集成测试中处理状态,则需要进行模拟.
摘要
根据您希望集成测试的高级程度以及您希望它与实际执行模型的接近程度,您可能最终必须模拟并替换大量的类/接口.在Web引用应用程序示例 https://github.com/Azure-Samples/service-fabric-dotnet-web-reference-app有需要的类嘲笑的一些实施,也https://github.com/loekd/ServiceFabric.模拟包含用于测试的模拟,但如果您真的想要运行集成测试而不仅仅是单元测试,则可能需要更改代码.