Is it just me that has this constant problem of tr...
# random
c
Is it just me that has this constant problem of trying to write unit tests for a class i wrote? the method I want to test is private. So then I have like 4 options: 1. i can make it public 2. I can annotate it @OpenForTesting (or whatever) 3. i can just pull that logic out into another class and test that class 4. forget about testing the individual unit and instead test the public method(s) that invoke the private method none of those seem good enough in my current scenario. i think i should go option 3. but then this new class I would make would have a bunch of member fields that you'd need to pass into it, and so you lose a lot of that conveninece. and with that line of thinking... its like. i should never have private methods because i can't test them. am I missing something here? what do people typically do in this case?
4️⃣ 9
c
The short answer is do #4.
👍🏽 1
👍 8
👍🏻 1
In typical OOP I would say the “unit” under test is the class, not the method
I have no idea if this is the common belief tbh, it’s just how I learned it. But private methods are implementation detail. Testing them makes no sense.
💯 4
s
If a function is private then it doesn’t expose a testable contract to the outside world and doesn’t need testing
👍🏻 1
👍 4
👍🏾 1
p
I think also you should keep in mind that testing should cover the behavior of the unit not its concrete implementation. If you are testing private methods you are testing part of the implementation of class that is provided by the public API.
☝🏽 1
☝️ 1
☝🏾 1
r
Yep, only testing public methods is the way to go. Imagine you some day refactor the class to completely change the implementation (add, remove and rename private methods but don’t change any behaviour or public contract). You then explicitly want to test that the public methods still behave as before according to the documented behaviour. Having to spend ages rewriting private method tests is not just a waste of time, it’s actively harmful because you’re likely to miss behaviour changes that you’re supposed to be testing
👍 2
Of course if you’re finding the public methods are doing too much and are hard to test it may make sense to do 3 but this is a code improvement, not just for testability
t
I’ll join the general call for Option 4 - private functions should not be directly tested, a class that contains them should be tested through its public contract only. I’d also advise you NOT to do Option 5, which a coworker of mine attempted briefly before I had them stop. Option 5: Make a copy of the private method in the JUnit for the class, and test that. Thankfully, they didn’t do too many of these and I was able to convince them that Option 4 is the way to go, but man, it was a bit of a panic when I saw them for the first time.
😧 4
y
Also, your options aren't just public vs private. If a function in a class shouldn't be exposed to a consumer of your library, but it's still used internally, you can mark it
internal
, and tests have access to such internal functions
p
I've seen a lot in my career but option 5 is really something that would lead to restless sleep 😬
👌 2
m
#4 is considered best practice. I'll admit on occasion I will temporarily make it public, test the $#@! out of it, move it to private and remove the test(s). This is assuming the test of the public functionality that calls it already exists and continues to pass.
👍 1
c
lmaooo. thats what i just did