2

I have a method in my Service fabric Stateless service application which get the configuration stored in Settings.xml from ServiceContext

public static string GetConnectionString()
{
    if (context == null)
        return string.Empty;

    // return context.CodePackageActivationContext.GetConfigurationPackageObject("Config").Settings.Sections["MySection"].Parameters["ConnectionString"].Value;

    ICodePackageActivationContext activationContext = context.CodePackageActivationContext;
    ConfigurationPackage configPackage = activationContext.GetConfigurationPackageObject("Config");
    ConfigurationSettings configSettings = configPackage.Settings;
    string connectionString = configSettings.Sections["ConnectionData"].Parameters["ConnectionString"].Value;
    return connectionString;
}    

In the above code I split the code into many lines for easier understanding, actually i use the commented code in my application.

I need to write unit test for this method. I could mock ServiceContext and ICodeActivationContext

But i could not create objects for ConfigurationSettings and ConfigurationPackage since they have internal constructors.

How do I isolate these classes in my unit test. Or should i exclude the service context part from my unit test.

abatishchev
  • 98,240
  • 88
  • 296
  • 433
Binu Vijayan
  • 803
  • 1
  • 9
  • 24

3 Answers3

3

Now you can use a NuGet package named ServiceFabric.Mocks, which offers mocks for most Service Fabric classes.

For example, you can use MockStatelessServiceContextFactory.Default to get a StatelessServiceContext mock.

pberggreen
  • 928
  • 6
  • 13
  • That will work! Please have a look at this file, that explains how to test code that uses configuration: https://github.com/loekd/ServiceFabric.Mocks/blob/master/test/ServiceFabric.Mocks.Tests/ServiceTests/ConfigurationPackageTests.cs – LoekD May 31 '18 at 05:54
1

I would create an interface that returns parameters from service fabric (one of them is the connection string). Then a class that implements the interface the way you wrote in the question. And that interface can be mocked used in unittesting. The result is - that you cannot test the method that actually read from service parameters, but at least you can test everyone who uses it without the need to mock ServiceContext and alike.

Philip Patrick
  • 311
  • 4
  • 6
  • That is what i did in the end, We had a call with microsoft SME guy and he said , in the current version we cannot mock the ServiceContext since it is a very complext object. The recommended way was like you mentioned in the above comment.. Thanks ! – Binu Vijayan Jun 13 '16 at 09:08
0

I had an almost identical issue with the System.Printing PrintSystemJobInfo class, it has a sealed constructor so it proved very difficult to mock. I assume you are creating an interface that closely resembles the class you wish to mock, then creating a wrapper for the actual class that implements the interface.

A solution to your problem is to pass the parent class as a parameter in the constructor of the child class (so the child class has access to the parent methods and can build the real implementation that you intend to wrap).

The following code demonstrates how I did it with PrintSystemJobInfo;

using System;
using System.Printing;

namespace ConsoleApplication6
{
class Program
{
    static void Main(string[] args)
    {
        var server = new LocalPrintServer();

        IPrintQueue testablePrintQueue = new RealPrintQueue(server);

        IPrintSystemJobInfo  printSystemJobInfo = testablePrintQueue.AddJob();

        var result = printSystemJobInfo.IsBlocked;

        Console.WriteLine(result);

    }

    public interface IPrintSystemJobInfo
    {
         bool IsBlocked { get; }
    }

    public interface IPrintQueue
    {
        IPrintSystemJobInfo AddJob();
    }
    public class RealPrintQueue:IPrintQueue
    {
        private PrintQueue _queue; 
        public RealPrintQueue(LocalPrintServer server)
        {
            _queue = server.DefaultPrintQueue;
        }

        public IPrintSystemJobInfo AddJob()
        {
            return new RealPrintSystemJobInfo(_queue);
        }

    }

    public class RealPrintSystemJobInfo: IPrintSystemJobInfo
    {
        private PrintSystemJobInfo job;
        public RealPrintSystemJobInfo(PrintQueue queue)
        {
            job = queue.AddJob();
        }

        public bool IsBlocked
        {
            get { return job.IsBlocked; }
        }
    }
}

}

I have tried to keep this as simple as possible so I have only wrapped IsBlocked property, but you could extend it to what ever you liked (obviously).

mark_h
  • 5,233
  • 4
  • 36
  • 52
  • p.s. If my answer doesn't work (sorry I tried), consider changing the title of your question (I've no idea if you actually can), I don't think your current title describes your very valid issue well. E.g How to mock a class heirachy with sealed constructors... – mark_h May 18 '16 at 20:29