When testing your code you should pay attention to three areas:
- Scenario testing
- Functional testing
- Unit testing
Normally the amount of test you have in each category would have the shape of a pyramid, meaning a lot unit tests at the bottom, some functional tests in the middle, and just a few scenario tests.
With a unit test you mock out everything that the class under test uses and you test it in pure isolation (this is why it's important to make sure that inside your class you retrieve all dependencies trough injection so they can be replaced under test).
With unit testing you test all possibilities, so not only the 'happy path' but also all error conditions.
If you are completely certain that your all units work in isolation you write a couple of tests (functional tests) to make sure the units also work when combined.
Then you write a scenario test, which tests the wiring between all the functional modules.
For example, suppose you're testing a car.
You could assemble the whole car and as a driver check every possible condition but that would be really hard to do.
Instead you would test a small part of the engine with all possibilities (unit test)
Then you test the whole engine (separate from the car) which would be a functional test.
As a last test, you put your key in, start the car and drive it to the parking lot. If that's working then you know that all parts (battery, fuel, engine, ..) are connected and since you tested them in isolation you can be pretty sure that the whole car is functioning correctly.
So in your case, you tested all error conditions and the happy path in your unit test and know you only have to an end-to-end test with the 'real components' to check if the wiring is correct.
A few other points,
- Avoid conditional logic in your unit test. If you have to clean up, your using some kind of global state and the tests can suddenly influence each other.
- Don't specify any data that's not relevant for the test. If I would change forename, or surname, would the test fail? Probably not because it's the email address that's important but because you mention it explicitly in your test, I can't be sure. Try looking at the Builder Pattern for building your test data and making it explicit what's really important.
Generally, one would better be judicious about using protected access at all. The reasons for that are laid out in answers to prior questions over here: Why is Clean Code suggesting avoiding protected variables?
As for using it the way you think of here - weakening access limitation because it feels like more comfortable to test - it looks like a terribly bad idea.
The "right option" when you test functionality covered by private method is to leave its modifier alone and figure testing approach based on assumption that method is and will stay private.
There could be many cases and reasons when one needs to redesign code for testability. Various difficulties in writing unit tests often serve as good indication for such a need. But, "oh, that method is private" is not one of those indicative difficulties.
I wrote an explanation for this in an answer to prior question as a side note because that other question and answer were focused on different matters. But for the question you asked, it seems to apply fully and directly, so I will simply copy that part over here.
<rant "I think I heard enough whining. Guess it's about time to say loud and clear...">
Private methods are beneficial to unit testing.
Note below assumes that you are familiar with code coverage. If not, take a time to learn, since it's quite useful to those interested in unit testing and in testing at all.
All right, so I've got that private method and unit tests, and coverage analysis telling me that there's a gap, my private method isn't covered by tests. Now...
What do I gain from keeping it private
Since method is private, the only way to proceed is to study the code to learn how it is used through non-private API. Typically, such a study reveals that reason for the gap is that particular usage scenario is missing in tests.
void nonPrivateMethod(boolean condition) {
if (condition) {
privateMethod();
}
// other code...
}
// unit tests don't invoke nonPrivateMethod(true)
// => privateMethod isn't covered.
For the sake of completeness, other (less frequent) reasons for such coverage gaps could be bugs in specification / design. I won't dive deep into these here, to keep things simple; suffice to say that if you weaken access limitation "just to make method testable", you'll miss a chance to learn that these bugs exist at all.
Fine, to fix the gap, I add a unit test for missing scenario, repeat coverage analysis and verify that gap is gone. What do I have now? I've got as new unit test for specific usage of non-private API.
New test ensures that expected behavior for this usage won't change without a notice since if it changes, test will fail.
An outside reader may look into this test and learn how it is supposed to use and behave (here, outside reader includes my future self, since I tend to forget the code a month or two after I'm done with it).
New test is tolerant to refactoring (do I refactor private methods? you bet!) Whatever I do to privateMethod
, I'll always want to test nonPrivateMethod(true)
. No matter what I do to privateMethod
, there will be no need to modify test because method isn't directly invoked.
Not bad? You bet.
What do I loose from weakening access limitation
Now imagine that instead of above, I simply weaken access limitation. I skip the study of the code that uses the method and proceed straight with test that invokes my exPrivateMethod
. Great? Not!
Do I gain a test for specific usage of non-private API mentioned above? No: there was no test for nonPrivateMethod(true)
before, and there is no such test now.
Do outside readers get a chance to better understand usage of the class? No. "- Hey what's the purpose of the method tested here? - Forget it, it's strictly for internal use. - Oops."
Is it tolerant to refactoring? No way: whatever I change in exPrivateMethod
, will likely break the test. Rename, merge into some other method, change arguments and test will just stop compiling. Headache? You bet!
Summing up, sticking with private method brings me a useful, reliable enhancement in unit tests. In contrast, weakening access limitations "for testability" only gives me an obscure, hard to understand piece of test code, which is additionally at permanent risk of being broken by any minor refactoring; frankly what I get looks suspiciously like technical debt.
</rant>
Best Answer
You don't have to test .NET Framework's code in your specific case, because:
You can't inherit from
Convert
class, since this class is static; even if you could do that, for example ifConvert
class weren't static:The
Convert
class has no virtual methods,There are no instance methods,
There are no abstract methods,
You cannot override static methods in a class,
You shouldn't hide methods by using
new
keyword anyway (and if you do, Code analysis will shout at you).The only way you may be able to screw with existent functionality is through Reflection. If you use Reflection in order to play with the internals of the
Convert
class, then yes, you have to study and test the impact it may have.Otherwise, you just have to test the new code you'll write in your custom class.