Academic Integrity: tutoring, explanations, and feedback — we don’t complete graded work or submit on a student’s behalf.

I am quite a beginner in code testing, and was an assert whore before. One thing

ID: 643030 • Letter: I

Question

I am quite a beginner in code testing, and was an assert whore before. One thing worrying me in unit testing is that is often requires you to make public (or at least internal) fields that would have been private otherwise, to un-readonly them, make private methods protected virtual instead, etc...

I recently discovered that you can avoid this by using things like the PrivateObject class to acces anything in an object via reflection. But this makes your tests less maintainable (things will fail at execution rather than compile time, it'll be broken by a simple rename, it's harder to debug...). What is your opinion on this ? What are the best practices in unit testing concerning access restriction ?

edit : consider for instance that you have a class with a cache in a file on disk, and in your tests you want to write to memory instead.

Explanation / Answer

You should never-ever have to

make public (or at least internal) fields that would have been private otherwise, to un-readonly them, make private methods protected virtual instead

Especially un-readonlying a field can make an immutable object mutable, and that would be a disaster.

Your tests should consider your objects as black boxes (Wikipedia), meaning that they should only be concerned with the public interface of the objects, not with details of their implementation.

If an object cannot be sufficiently tested using its public interface, then you need to find ways to provide formal and useful extensions to its interface that would facilitate testing. For example, a registration system with only a pair of Register/Deregister methods would perhaps benefit from an IsRegistered method even if it is not necessary for the application at hand; still, it is a formal and useful extension to the interface, and it will, incidentally, accommodate testing.

The important thing is that changing the implementation of the object should not require you to change the unit test. In theory you should be able to write the unit test once, and then ask multiple programmers to code multiple entirely different implementations of the object-to-be-tested to work with the unit test.