Scenario. Language C#, Unit testing using VS2008 Unit testing framework
I have a static class with a static constructor and 2 methods.
I have 4 test methods written to test the entire class.
My Static Constructor has some important initializations.
Now if I run all the 4 unit test cases in tandem, the static constructor will be
called only at the beginning. At the end of each test case, there is no such thing
called static destructor, So the state info in the constructor gets carried to the
next unit test case also. What is the workaround for this.
Type staticType = typeof(StaticClassName);
ConstructorInfo ci = staticType.TypeInitializer;
object[] parameters = new object[0];
ci.Invoke(null, parameters);
from http://colinmackay.scot/2007/06/16/unit-testing-a-static-class/
The simplest solution is to add a "Reset" method to your static class, which would have the equivalent behaviour of destructing it and reconstructing it.
There may be a valid reason why you are using a static class here. However, because statics don't play nicely with unit tests, I usually search for an alternative design.
I would move the initialization from the static constructor to a method that is called by the constructor. By making this method internal, you can then call this method from your tests to reinitialize the class.
public static class MyClass
{
public static MyClass()
{
initialize();
}
internal static void initialize()
{
// Do initialization (and cleanup if necessary)
}
public static void Method1() {}
public static void Method2() {}
}
In order to call the internal methods you need to use the InternalsVisibleTo attribute, as described in this blog.
You can also make it private, but then you need to use reflection to call it.
But as Andrew Shepherd said, you should also check if a static class is the best design of this class.
With out knowing the usage of the class commenting on just the usage is of cause a bit tricky but ill give it a go anyways. To me the above sounds like a smell more than a testing problem.
A static class (just as singletons) are basically a collection of global functions/variables which generally is a bad thing in oop. I'd say trying to test the test issue is (eventhough probably the easiest right now) only fixing the symptom but not the problem.
I'd suggest to take a look at the desing a concidere if you really need the static class or if it just seemed like the easiest way to fix a problem at the time
For the sake of completeness, if you need to reset a non-public field/variable of a static class, it is also possible to do so via reflection.
using System.Reflection; // or Mono.Reflection
public static class MyClass{
private static string myString;
}
var newValue = "Potatoes";
var field = typeof(MyClass).GetField("myString", BindingFlags.Static | BindingFlags.NonPublic);
field.SetValue(null, newValue); // the first null is because the class is static, the second is the new value
Well, you didn't specify which language you were using, but if there is a way to open up your static class from within the test file, then I would add a fake destructor to it, which you can call after each test. That way, the 'destructor' stays in the test class, and out of your production code.
You could use Typemock's Isolator which is capable of mocking static classes, so in each test you can "define" how the static will be operating.
It's not a free product though.
It sounds like you're trying to test the static constructor. This seems like a bad idea.
Consider extracting the initialization logic into a separate (non-static) class instead.
For the sake of discussion, let's say your static class is called MySingleton, and let's say you create a new class called MyInitializer, with an Execute method. MySingleton's static constructor could instantiate MyInitializer and call Execute, which does all the initialization.
Then your production code could use MySingleton, and ignore MyInitializer. Your tests, on the other hand, could ignore MySingleton, and merrily create a new MyInitializer instance for each test, getting a fresh start each time.
Related
Static classes in legacy applications are hard to use in unit tests because you cannot mock them.
What is a simple way to convert them across the whole application to regular classes that use an Interafce?
It is easiest and less risky to do this in two steps.
The first step is repetitive and uncreative and can be assigned to a junior engineer or could even be done with a small program.
For each class, follow these steps:
Remove the static keyword from the desired methods and properties.
Add a static member called Instance that contains an instance of the class. Yes, we're making a singleton.
//Old class
static class MyHelpers
{
public static string Foo(string x) { /* Implementation */ }
}
//New class
class MyHelpers
{
public static MyHelpers Instance { get; } = new MyHelpers();
public string Foo(string x) { /* Implementation */ }
}
In the rest of your code base, replace static calls with calls to the instance.
//Old code
MyHelpers.Foo("Hello world");
//New code
MyHelpers.Instance.Foo("Hello world");
Compile to make sure you didn't miss any spots
Test & check in source code
The second step is optional. We really want to get rid of those Instance keywords as they break IoC (and if you keep a singleton in your code base other engineers will make fun of you). This will require you
Add one or more interfaces
Arrange for the class to be injected or otherwise made available everywhere Instance is used.
Search/replace to remove ".Instance" from all the calls.
The second step requires a little more thinking and should be assigned to a more intermediate engineer. If you have large code base, you can do this over time, or just make the change tactically as you touch code.
The simplest quick way: write a wrapper class with virtual methods in which static methods are called.
There are constrained and unconstrained mocking frameworks.
Former: Moq, NSubstitute, FakeItEasy allow to mock only virtual members.
Instead use unconstrained mocking frameworks. There are several of them: TypeMock, JustMock, MS Fakes, Prig, Ionad.Fody, Pose, Harmony, MethodRedirect. Unlike constrained frameworks, they allow you to substitute static methods and classes, mock private members, etc.
I was unclear in an earlier question I ask so I will try to be more explicit.
Is there a way to put a static class inside of a dictionary so that its functions can be called? If this is not possible, what is the best alternative that doesn't involve using instances that you can suggest?
Here is how I would like to use it:
static class MyStatic : IInterface
{
static void Do(){}
}
static class MyStatic2 : IInterface
{
static void Do(){}
}
class StaticMap
{
static Dictionary<Type,IInterface.class> dictionary = new Dictionary<Type,IInterface.class>
{
{Type.1, MyStatic}
{Type.2, MyStatic2}
};
}
// Client Code
class ClientCode
{
void Start()
{
StaticMap.dictionary[Type.1].Do();
}
}
There are some fundamental reasons why you can't do that directly:
Static method calls are bound at compile-time
Static calls are not inherited - they are tied to the class that defines them
There is no implicit base type (and therefore no polymorphism) between static methods, even if the name, inputs, and outputs are all the same
Since your signature is the same for every static method, you could store a Action in the dictionary instead:
static Dictionary<Type,Action> dictionary = new Dictionary<Type,Action>
{
{Type.1, MyStatic.Do}
{Type.2, MyStatic2.Do}
};
then you can call the Action directly:
void Start()
{
StaticMap.dictionary[Type.1]();
}
It's slightly repetetive because you have to specify the method name in the dictionary as well, but it's type safe.
A key question is whether you want to call a single method on each type or whether you need to call multiple methods belonging to each type.
If it's just a single method, then what D Stanley suggested is the answer. If you store a number of Actions, each representing a method with the same signature on a different static class, then you're accomplishing what you said.
However that raises a question - why the constraint that each method must belong to a separate static class? This approach would work just as well if some or all of the methods belonged to the same class.
If you need to call more than one method from each class then an Action no longer works. You'd have to store collections of Action, which a) means class instances, and b) is a lot more complicated than just using interfaces and class instances.
One way to manage instances is by using a dependency injection container to create class instances for you. Using that approach, you can create non-static classes without having to go through the hassle of explicitly making them singletons. But you can tell the container to only produce one of each and reuse it. For example, using Castle Windsor:
container.Register(Component.For<ISomeInterface,SomeClass>));
Now every time the container is asked to provide an instance of ISomeInterface it will always provide the same instance of SomeClass.
Because the dependency you're looking for varies by type (Dictionary<Type, Something>) it sounds like what you're looking for might be related to generics. But it would be necessary to take a step back from the smaller problem and understand a slightly larger picture of what you're trying to accomplish.
Instead of having the entire class as static, create a Singleton instance.
public class Foo
{
public static Foo _Foo;
public Foo()
{
_Foo = this;
}
}
Then you may add it to your list, and also inherit from Interfaces, etc.
I'm a little confused about how to perform these test. I know about the existence of PrivateObject to test private class and PrivateType to test private static class, but how can I test a private static method of a PUBLIC static class?
public static class Clients {
// CUT
private static List<string> GenerateAddresses(string AppPath) {
// CUT
}
}
In my unit test class I tried
PrivateType testClients = new PrivateType(Clients);
but I get the error
'Clients' is a type, which is not valid in the given context
The error is a bit confusing and google bring me to completly different problems. Am I using 'Clients' wrong with PrivateType? Or should I test in a different way given that Clients is public?
Or should I test in a different way given that Clients is public?
Yes: Clients is the unit you're testing. If it's not exposing GenerateAddresses publicly, it's not part of its surface API, and in theory is just there to support the internals of the class.
In unit testing, test the observable behaviour of the class - don't worry about how it goes about doing it internally.
var testClients = new PrivateType(typeof(Clients));
PrivateType expects a Type object rather than the symbol name.
But I would rather suggest re-thinking your test strategy. Testing private methods is usually not required. If you find that you are not able to get a decent code coverage from the public methods you may be in need for some refactoring.
I have a method that accesses variables local to the class itself. I'm wondering if that's a design flaw because now my unit tests are dependent on those variables being set. Is it weird/wrong to pass those variables to the method, even though that method has direct access to those variables? (If the method accepts those variables as parameters, then the unit test can also pass its own variables to the method.)
For example, here are the variables local to the class:
private static List<string> _whitelistNames = GetWhitelistNamesFromConfig();
private static List<string> _blacklistNames = GetBlacklistNamesFromConfig();
And the method looks something like this:
private static bool ThisProcessorHandlesThisFoo(Foo foo)
{
if (_whitelistNames.Count > 0)
{
// We're doing this instead of Contains() so we can ignore case sensitivity.
bool found = ListContainsString(_whitelistNames, foo.Name, StringComparison.OrdinalIgnoreCase);
// Some logging here
return found;
}
if (_blacklistNames.Count > 0)
{
bool found = ListContainsString(_blacklistNames, foo.Name, StringComparison.OrdinalIgnoreCase);
// Some logging
return !found;
}
throw new InvalidOperationException("some message");
}
In order to do what I'm suggesting, I would need to change the method signature to this:
private static bool ThisProcessorHandlesThisFoo(Foo foo, List<string> whitelistNames, List<string> blacklistNames)
Then the calling code (in the same class) would have to pass the local variables to the method. This would allow my test code to send its own parameters. Am I missing something? Is there a better way to do this? (It just seems odd to pass parameters that the method already has access to. But perhaps this is a good decoupling technique.)
You shouldn't have to worry about this.
Your unit tests should be testing the interface to your class (public methods and properties), and should not depend on any implementation detail (like a private class property). This allows the implementation to change without breaking other code (and hopefully without breaking existing tests).
Those private static fields should be initialized when the class is instantiated (according to your code, they have initializers). Are they initialized when it's instantiated for your unit test? They should be... It's a generally accepted idea that when the constructor for an object is finished running, the class should be in a usable state, and you're indicating that this isn't always the case.
This is an example of where something like Dependency Injection could be useful. You then pass these kinds of things to the constructor of your class (or through another means), and allow the part of the program that creates it (either your normal program or your unit test) to "inject" them into the class.
You should not test private methods, test the public ones in the way that tests cover all the class' code branches(including ones in private methods).
I'd recommend you to change method signature(to ThisProcessorHandlesThisFoo(Foo foo, List<string> whitelistNames, List<string> blacklistNames)) rather than use fields. As per my experience, such approach makes classes much easier to read and maintain.
I just finished coding a class, and realized that all of its public functionality is encapsulated in a single method. It has no properties, no shared resources, and requires no constructor overload and handles disposal of anything it uses. It looks something like this:
public class ReportGenerator
{
public string GenerateReport(List<SomeClass> stuffToReportOn)
{
string fileName = String.Empty;
using(var reportDs = CreateDataSet(stuffToReportOn))
{
//do the stuff with the third party tool that
//creates the report.
//Construct the filename.
//Save the report.
}
return fileName;
}
private TypedDataSetRequiredByThirdPartyLib CreateDataSet(List<SomeClass> reportItems)
{
//create the dataset, calling two other private methods
//to build the tables/rows
}
}
After I finished refactoring it, I realized that this class could be entirely static. My question is, should it? Should a class that encapsulates all of its functionality in one public method be made static?
No. and what are the expected benefits?
Far more important is the potential for errors. If in your class you declare a static variable, it'll only get initialised once, its value will persist and each call will potentially behave differently. Easily over-looked, this can be difficult to debug.
No, it will make writing unit tests for this class - or classes that use this class - impossible.
With a tool like FakeItEasy, you don't even need the class to implement an interface to be able to mock it (which means you can get started quickly mocking an old code base that wasn't written with TDD in mind), but it can't get around static calls.
UPDATE
Lets say you need to unit test a method GenerateWidgetReports that calls ReportGenerator.GenerateReport. You need to ensure stuffToReportOn contains only Widget1 & Widget2. How do you code that test?
What you end up doing is having GenerateWidgetReports use a method called GetStuffToReportOn, you can test that, fine. GenerateWidgetReports then just becomes glue that calls GetStuffToReportOn and passes it's result to ReportGenerator.GenerateReport.
However you still have no test for GenerateWidgetReports, because you can't call it without actually generating the report.
Ideally the class with GenerateWidgetReports takes an IReportGenerator object, you mock the GenerateReport method and test in there for Widget1 & Widget2.
You can't do any of this with any Mocking tool if GenerateReport is static.
Update 2
I stand corrected, TypeMock can intercept and re-direct calls to static methods. See this answer
Other than difficulty in unit testing, you should ask yourself:
Do I make changes to the parameters? If so, how often?
Does the object need to have a state?
Do I need to keep the object around after the process?
If you determine that making it a static class works for you, you could also decide to go one step further and make an extension method:
public static class ReportExtension
{
public static string GenerateReport(this List<SomeClass> stuffToReportOn)
{
string fileName = String.Empty;
using(var reportDs = CreateDataSet(stuffToReportOn))
{
//do the stuff with the third party tool that
//creates the report.
//Construct the filename.
//Save the report.
}
return fileName;
}
private static TypedDataSetRequiredByThirdPartyLib CreateDataSet(List<SomeClass> reportItems)
{
//create the dataset, calling two other private methods
//to build the tables/rows
}
}
Pretty sure I have my formatting correct for an extension method.
Edit:
You still have the issues of unit testing because code depends on this static method. Ultimately, you will have to decide on the pros and cons and make the decision yourself. I could be wrong, but if you were to unit test the dependent code with this as an instance class, you can gain some confidence that it should be fine as a static or extension method.
Yes, it would make using your class a lot easier.