var type = Type.GetType("MyProject.MyClass"); var methodInfo = type.GetMethod("TheMethod"); var classInstance = Activator.CreateInstance(type, null); methodInfo.Invoke(classInstance, null);
That is quite a bit of work. Of course you could create some test infrastructure to avoid duplication in every tests or you may find libraries online for that. But still, writing tests like this smells funny to me.
In short, you should never write tests directly against a non-public class.
Let's take a look at the 2 possible cases for this: the private class and the internal class.
The case of the private class
For a class to be private means it is nested inside another classpublic class A { // ... private class B { // ... } }
In a situation like this
class B
can only be used by class A
. Anything class B
do is only for serving class A
. If you want to test a method in class B
you should find out how class A
use class B
and write your tests against class A
public API.If you find there is no way to reach the method you want to test in
class B
through class A
it simply means that you just found dead code! If you found a way but find it too hard to setup a test then maybe class B
is not simply a private utility class. In that case I would extract class B
from inside class A
and change its access modifier to internal
. Unfortunately, now any class inside the same assembly could use class B
. It is a trade-off I'm willing to pay because this case is really rare and C# still lack a proper access modifier scoped to the current namespace.The case of the internal class
Internal class could also be tested through reflection. Personally I prefer to use theInternalsVisibleToAttribute
and give access to internals types to my unit test project. To do it you need to add the attribute to the project under test AssemblyInfo.cs
file like this[assembly: InternalsVisibleTo("Contoso.MyApp.UnitTests.dll")]
If your project is signed you will need to also provide the assembly's public key like this
[assembly: InternalsVisibleTo("Contoso.MyApp.UnitTests.dll, PublicKey=1234...789")]
Again, this is a trade-off: you give special access to your internal types only for testing but it is way better than changing the class access modifier to
public
. You should never change a type access modifier to public
for testing!Conclusion
I always try to write tests againstpublic
classes and methods. Sometime an internal class will grow to be very complex over time and become its own new component. In a solution were we create a lot of small projects we would simply create a new one for such component and expose it publicly but that is not what I do. I usually try to create the minimal number of projects in my solution so testing internal
classes using the InternalsVisibleToAttribute
is a good trade-off for me.
2 comments:
Hello Pascal.
The Article on Unit test smells the non public class is very informative. It give detail information about it .Thanks for Sharing the information on Unit testing . mobile application testing
Wow, What a Excellent post. I really found this to much informatics. It is what i was searching for.I would like to suggest you that please keep sharing such type of info.Visit here for Penetration testing services and Software testing services
Post a Comment