I've got a static class that I am using for logging:
public static class myLogger
{
public static ErrorLogging(string input)
{
//dostuff
}
}
The way I am using it is:
public class myClassthatDoesStuff
{
...
myLogger.ErrorLogging("some error ocurred");
...
}
How can I moq the myLogger class in order to be able to unit test it and ensure that the ErrorLogging method was executed? Is it possible to do this without setting any parameters in the constructor (constructor injection)? myClassthatDoesStuff requires that there are no parameters in the constructor.
A static method that holds no state or doesn’t change state can be unit tested. As long as the method and its dependencies are idempotent, the method can be unit tested. The problems arise when the static method calls other methods or when the object being tested calls the static method.
The static method holds state information, i.e., if it caches data into a static object of the class. Consider the following code snippet that shows two classes, namely ProductBL and Logger.
Wrap the static class with an instance class and delegate calls: We can create an interface that expose all the functionality of the static class. Then all we need to do is wrap it with a simple class that will delegate the calls to the static class: // the interface should look exactly like the static class we want to wrap !
As long as the method and its dependencies are idempotent, the method can be unit tested. The problems arise when the static method calls other methods or when the object being tested calls the static method. On the other hand, if the object being tested calls an instance method, then you can unit test it easily.
This blog post describes the exact same scenario - you have an old static logging method and want to use it in testable code.
Wherever you would have depended on the static class, depend on the interface instead. For example, if class DoesSomething
requires the function in your static class, do this:
public interface ILogger
{
void ErrorLogging(string input);
}
public class MyClassthatDoesStuff
{
private readonly ILogger _logger;
public MyClassthatDoesStuff(ILogger logger)
{
_logger = logger;
}
}
This gives you two benefits:
You can unit test code that will use that static class (by removing the direct dependency on that static class.) You can replace ILogger
with a mocked class, like one that adds your error messages to a list.
class StringLogger : List<string>, ILogger
{
public void ErrorLogging(string input)
{
Add(input);
}
}
var testSubject = new MyClassthatDoesStuff(new StringLogger());
If you can not change it from a static to a non-static class, wrap it with a non-static class...
void Test()
{
string testString = "Added log";
var logStore = new List<string>();
ILogger logger = new MyTestableLogger(logStore);
logger.ErrorLogging(testString);
Assert.That(logStore.Any(log => log==testString));
}
public interface ILogger
{
void ErrorLogging(string input);
}
public class MyTestableLogger : ILogger
{
public MyTestableLogger(ICollection<string> logStore)
{
this.logStore = logStore;
}
private ICollection<string> logStore;
public void ErrorLogging(string input)
{
logStore.Add(input);
MyLogger.ErrorLogging(input);
}
}
public static class MyLogger
{
public static void ErrorLogging(string input)
{
// Persist input string somewhere
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With