Let's start by confirming that this is partly a religious discussion .
It is my point of view that testing private methods is something you often need to avoid, but there are exceptions.
Why shouldn't I test private methods?
Since you are checking to see if your application is working, it is not necessary how it works. The private method is not part of the API that your program provides, and it is essentially an implementation detail.
The general argument against working with the restrictions set for you by encapsulating and testing is that it can violate your tests that verify this particular implementation.
In "normal" testing, we test the public methods because they form our program: if we know all the public APIs, then we know that the program will work. If your application is well structured, you will have several levels of APIs that will constantly improve tests for smaller units, so you have a clear overview where something may go wrong as it is somewhere below.
What you need to know about private methods is that they will always be called at some point by the public method, which will be tested. The private method is an implementation detail of your device under test and as such should not be tested separately.
This helper method is not bound by the API and therefore there is no guarantee that it will remain unchanged; changing implementation detail without adjusting overall functionality will now break your test using this method. Therefore, even though your program is still working fine, you now have a broken test. These tests are unstable: a refactor that does not change your functionality may still need to remove unit tests because they are no longer relevant (which is dangerous in itself because you have to be sure that the test is actually redundant).
Why should I test private methods?
Only a few things are black and white, and this is not one of them. I believe that the new code should not test private methods, but where I am making the difference is: new code.
If you inherit an outdated code base, the likelihood that the architecture is not very pretty. You may have to jump over hoops and perhaps the best code will be better.
So, the first thing you do is write some unit tests that are guaranteed to tell you when you break the functionality. So far so good, we can now move on to the actual refactoring process. Let's start with this method of 500 private lines?
Keeping the previous comments, you will need to look at the code and see which public methods use this private method and monitor them when changes are made.
For ease of use, I would write tests here that check only the contract of this private method against the rest of your application: as long as your result does not differ from the method, you know that this will not affect any other inherited methods. Thanks to this knowledge, you can now comfortably reorganize everything inside this method. When break; does something, you can immediately work with your helper method instead of going through public API methods.
Keep in mind that I would only do this for large refactoring operations: these are, first of all, time tests, and the "implementation detail" actually consists of 500 lines of code: this part with a lot of details in itself.
How to check private methods?
You have several options here on how to make them available for testing:
Reflection
I believe this is what WhiteBox uses. However, this raises some eyebrows: there is no static typing (changing the method means breaking the test), it is expensive , and code using reflection is usually harder to read.
Privateobject
I did not look at the exact implementation, but I am sure that it uses reflection behind the scenes. Basically, this provides an approach to reflection through a convenient interface. I have not seen it used a lot (partly because I would use reflection as an absolute last resort), but it is there.
MSDN
Production
This would be my first approach: is this helper method important enough to make it stand on its own? Most likely, you will say yes to this, because, apparently, it is already important enough that you want to conduct an explicit test.
Public
The most obvious choice: just make it public . This follows the same idea as Prey: "can it stand on its own?" The difference here is that you still consider it part of the current class, you just increase its access, while fetching it in another class also indicates that you are talking more than just a helper method.
Interior
This parameter takes the middle route: if I make it internal (C # context) and use the [InternalsVisibleTo] attribute, you can make it internal , giving the test assembly the opportunity to test it (and still hold it from the public API).
This leads to the fact that people see in it only implementation details and change the implementation when the tests break (which explains the specific implementation).
In addition, it also increases the connection between your application and tests.
Everything is believed to depend on your own preferences: there are several options for testing private methods, and there are some arguments for both sides. Personally, I would stay away from the hassle of testing such implementation details and instead look at what I can do to improve my architecture. Most likely, the problem will be solved that way.