Is it possible to write methods, which are only callable by unit tests? My problem is that our framework contains a lot of Singleton
classes, which makes unit testing quite hard some time. My idea was to create a simple interface like this:
public interface IUnitTestClearable
{
void ClearForUnitTest();
}
This method will be called for "resetting" singleton instances for better handling of unit tests. But this method should only be callable from unit test classes/instances. Is this possible?
A unit test should test the public contract, the only way how a class could be used in other parts of the code. A private method is implementation details, you should not test it; as far as public API works correctly, the implementation doesn't matter and could be changed without changes in test cases.
Yes it is very bad practice - you're letting your tools make design decisions for you. I think the main problem here is that you're trying to treat each individual method as a unit. This is generally the cause of all unit test woes.
Moq supports mocking protected methods. Changing the methods to protected , instead of private , would allow you to mock their implementation.
Unit Tests Should Only Test Public Methods The short answer is that you shouldn't test private methods directly, but only their effects on the public methods that call them. Unit tests are clients of the object under test, much like the other classes in the code that are dependent on the object.
You can make a method internal and then set InternalsVisibleTo. This way, you give another assembly access to your internals
http://geekswithblogs.net/jwhitehorn/archive/2007/11/09/116750.aspx
but Tim was just before me as I end this :)
In your project file, AssemblyInfo.cs, set
[assembly: InternalsVisibleTo("Application.Test")]
or if you have a signed assembly
[assembly: InternalsVisibleTo("Application.Test, PublicKey=KEYHERE")]
Providing access to unit tests while controlling or preventing other things (ab)using that access is a good idea. There are a number of ways this can be done but the simplest is to use InternalsVisibleTo
https://docs.microsoft.com/en-us/dotnet/api/system.runtime.compilerservices.internalsvisibletoattribute
You may not want to expose all private methods to your unit tests, as it might cause confusion, so just add a private method for your singleton classes.
public class MySingleton
{
private void ClearForUnitTest()
{
Console.WriteLine("Cleared.");
}
}
Create extension to be used in your unit tests.
public static class PrivateExtensions
{
public static void ClearForUnitTest<T>(this T instance)
{
var method = typeof(T).GetMethod("ClearForUnitTest", BindingFlags.NonPublic | BindingFlags.Instance);
method.Invoke(instance, null);
}
}
Use like it would be public
private static void Main(string[] args)
{
var ms = new MySingleton();
ms.ClearForUnitTest();
}
profit
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