Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 497
ujjwal Manna Avatar asked Jan 21 '17 17:01

ujjwal Manna


People also ask

What is integration testing explain its types with example?

This type of testing follows the natural control flow hierarchy, i.e., top to bottom. For example, you have a fitness app with four modules – A login page, a profile page, a workout page, and a payment page. The testing of the application will start from the crucial top-level module.

What is integration testing tool?

Integration testing tools are used to test the interface between modules and find the bugs; these bugs may happen because of the multiple modules integration. The main objective of these tools is to make sure that the specific modules are working as per the client's needs.


1 Answers

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.

like image 142
yoape Avatar answered Sep 21 '22 23:09

yoape