简体   繁体   中英

How we can perform integration test on service fabric (stateless service)?

I'ld like to perform integration on stateless service in service fabric.Please help me on this. I have created the stateless service like c# web api.

In order to perform integration tests on your Reliable Service there is a number of dependencies you need to mock and take care of. You will not be able to test all situations or behavior of your service this way, the way the FabricRuntime hosts and runs services is difficult to replicate (without writing your own FabricRuntime equivalency). It is also worth noting that there is no way to run FabricRuntime without a cluster (including local development cluster).

You also need to consider how advanced your integration tests should be. For instance, does your service call out to other service (including actors) within the same cluster using fabric transport (the default communication model) that you want to include in your integration test? Do you need to ensure that state is persisted across multiple activations of the same service partition?

First you need to get rid of all hard dependencies to FabricRuntime (to things with dependencies to it) and also static support classes in your code:

Service/Actor proxy

Don't use the static ServiceProxy.Create<..)(..)> when calling other services, instead make sure your Service accepts an instance of IServiceProxyFactory in the constructor and use that instance to create proxies to services your service calls. Same goes for ActorProxy.Create<..>(..) , replace this with an instance of IActorProxyFactory . In your program.cs where the service is constructed, give the service new ServiceProxyFactory() and new ActorProxyFactory() . That's the easy part, now you need to mock those so that your integration tests can actually create some form of proxy for downstream services. You will also need to create some form of container (like a mock FabricRuntime) that holds instances of called services and actors. It also gets tricky if you wan't to test that the RunAsync method of your service performs some function. Beware of creating this static though if you want to run it in a test runner, you don't want different tests to get mixed up in the same container.

Service context

You need to mock your StatefulServiceContext well and how your Service is created. Your Service constructors need to accept an instance of StatefulServiceContext to pass along to the base class, so you are free to supply your own mocked instances of context there when you create the service.

public StatefulService(StatefulServiceContext serviceContext)
    : base(serviceContext) {}

Service settings and activation context

You also need to see if your service implementation tries to read ICodePackageActivationContext or any of the settings from the Service manifest (like shown in this SO answer Where do you set and access run-time configuration parameters per environment for service fabric? ). In that case you need to replace it with your own mockable version and you need to inject that in the constructor as well. What you find in most samples is a call to the service context, like this:

this.Context.CodePackageActivationContext.GetConfigurationPackageObject("Config");

If you do it this way in your service then you need make sure you have a mock of StatefulServiceContext as well and how your Service is created. When you register your service with the runtime in Program.Main() then you get and instance of StatefulServiceContext in the register call:

ServiceRuntime.RegisterServiceAsync("ServiceType", 
    context => new Service(context)).GetAwaiter().GetResult();

State

In order to mock state and get it to behave similar to what it will when running in a real cluster you need to mock the underlying handler for reliable state: IReliableStateManagerReplica and you need to add an overloaded constructor to your services that accepts an instance of that and sends it to the base:

public StatefulService(StatefulServiceContext serviceContext, IReliableStateManagerReplica reliableStateManagerReplica)
    : base(serviceContext, reliableStateManagerReplica) {}

For actors its IActorStateProvider you need to mock if you want to handle state in your integration tests.

Summary

Depending on how advanced you want your integration tests to be and how close to the real execution model you want it to be, you may end up having to mock and replace a large number of classes/interfaces. The Web reference application sample https://github.com/Azure-Samples/service-fabric-dotnet-web-reference-app has some implementation of Mocks for required classes, also https://github.com/loekd/ServiceFabric.Mocks contains Mocks for testing, although you might need to alter the code if you really want to run integration tests and not just unit tests.

使用常规api对无状态web api进行集成测试没有区别。

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM