After spending more time with unit testing and this whole TDD thing, I’ve hit a barrier I wasn’t sure how to cross. How do you test internal and private members?
Before you even consider how to do so, you might consider why you are doing so. As Brody points out:
In theory you should only need to test your public methods anyway. Just have enough tests that you are testing all the code paths. In reality you may want to verify something works as expected before calling it with a whole lot more code.
If you are using TDD (Test Driven Development) this is not usually an issue as no code is written without a test so no code path should remain untested. Internal, protected and private methods are then spawned as you refactor against your existing tests.
Yes, I really need to test that
In my recent case, not only did I need to verify that each (internal) component of an algorithm I was developing, but this was the only way to test the algorithm. Due to it’s nature – a randomizer that causes no result to be guaranteed, it’s simply impossible to test the thing as a whole.
Okay, maybe not impossible. I suppose the randomizer could be implemented with an Interface that is mocked/faked and provided by the unit test… but I’m not going there.
Exposing internal methods with InternalsVisibleTo
Exposing your private methods is relatively easy. Just add:
to the AssemblyInfo.cs file of the assembly you want to access internal methods of. This will allow the assembly “UnitTestAssembly” – in this case – to see them. Unfortunately, this has no effect on private methods. Refer to Friend Assemblies.
Exposing private methods with PrivateObject
This was new to me pointed out by Emad Ibrahim in a recent blog post, but Microsoft already has an implementation to achieve this. The Microsoft.VisualStudio.QualityTools.UnitTestFramework assembly included with a Visual Studio test project (but not of course, if you built your own unit test assembly and use NUnit, for instance) has a class called PrivateObject which does the magic:
MyClass myObj = new MyClass(); var po = new Microsoft.VisualStudio.TestTools.UnitTesting.PrivateObject(myObj); string returnStr = (string)po.Invoke("DoSomethingPrivate");
It’s pretty simple – Instantiate your object that contains the private methods you need to test, create an instance of PrivateObject, passing in your object, and then calling PrivateObject’s Invoke() method, specifying the private method name.
With these workarounds, now any method can be unit tested regardless of it’s access modifier.