since the cache need not be visible to external consumers
A unit test is an external consumer. It's a class which invokes functionality on the object being tested, just like any other class.
Caveat: There is much opinion and debate on this matter. What I'm presenting here isn't "the one true answer" but is based on my own experience in maintaining unit tests in code.
Don't directly unit test private members. Not only does it generally take a little bit of trickery to make that happen, it creates coupling between the classes. (The test class and the class being tested.) Exposing the internals and coupling to them is a violation of object oriented principles.
Rather than thinking of your tests in terms of the methods you call on the class, think of your tests in terms of the functionality you invoke on the unit. Whatever functionality that unit exposes is what should be tested.
This leads to a few conclusions:
- If there is no public functionality which internally invokes the private members in question, then why are those private members there at all? Just remove them.
- If the private functionality is very complex and very difficult to invoke/validate using only public functionality then perhaps some refactoring is in order to simplify the class.
Since code which uses the object can only invoke the public functionality, code which tests the object should only validate the public functionality.