Reputation: 803
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.
Upvotes: 2
Views: 2605
Reputation: 958
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.
Upvotes: 3
Reputation: 341
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.
Upvotes: 1
Reputation: 5477
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).
Upvotes: 0