4 ms·
If you are making classes or methods public because you want to unit test them, you're doing it wrong. I've heard this a lot, but how do I test private methods
by dagw 5y ago
If you are making classes or methods public because you want to unit test them, you're doing it wrong.
I've heard this a lot, but how do I test private methods right? If my public method just calls 8 private methods (which each call out to a bunch of other private methods), how to I test to make sure all those private methods do what I want them to do so that I know which one is broken when my public method breaks.
- JoeNr76 5y agoAs others have said: you need to think about your functionality as a public API. How the API works under the hood shouldn't affect your tests. So how do you test private methods? You don't, with the exception of testing during development, but those aren supposed to be kept around.
- onli 5y agoThat your public function calls private functions is an implementation detail. It does not matter, test the public function. Subsequently that tests the private functions for all relevant input. There was recently a submission here on HN that talked about this and different perspectives on that topic. It's not a universally shared opinion, surprisingly.
- oxff 5y agoThis seems obviously correct to me and it's still not appreciated by many developer teams. Then there's the world of behavior / property / invariant -based testing which slims down your tests to essentially data generation and testing observable behavior which seems like magic to people still.
- UK-AL 5y agoYour expecting too much detail from your tests. As consequence your probably over-specifying them as well. Test through your public interface.
- teddyh 5y ago> how to I test to make sure all those private methods do what I want them to do so that I know which one is broken when my public method breaks. You don’t. You test only the public API. This way, you can refactor the public method to your heart’s content without any tests breaking.
- corpMaverick 5y agoI just try to be practical and make them protected so they can be called from the test class which lives in the same package. Perhaps adding a @VisibleOnlyForTesting annotation. The reality is that these private functions are building blocks that can be easier to test. If you only test the public methods, testing gets a lot more challenging and the methods are more difficult to test and the tests classes get a lot of more complicated. You end up creating more mocks or other doubles and bending backwards.
- BeetleB 5y ago> how to I test to make sure all those private methods do what I want them to do so that I know which one is broken when my public method breaks. Others have pointed out that you test only public methods. The thing I'd add to that: Having large classes is a code smell. If your class is big, it is probably several classes in one. Break it up accordingly. Some of your private methods in the big class will become public methods in the small class.
- goto11 5y agoIMHO the purpose of unit tests is to ensure the code is correct and allow you to safely refactor and introduce new functionality without breaking existing behavior. The purpose is not to pinpoint the exact line where the bug is, if a test fails. What you describe is white-box testing, where the test is coupled to implementation details of a class. This gives you more fine-grained reporting in case of an error but it makes it impossible to refactor the code safely. So I don't think that is a worthy trade-off. If you often have hard-to-locate bugs in particular large component, the solution is probably to refactor into smaller more loosely-coupled components with well-defined interfaces.
- anecd0te 5y ago
- monksy 5y agoThat's a sign that you're burrying too much functionality to make testing reasonable. It's a sign that you should start splitting that out to more generic functions. Scala is great about making these functions generic. Java has an issue with this where lots of things are easy to get burried but hard to reason about pulling them out.