To test isVarListSizeFive() I would have to call addVar() first 5 times to modify varList before testing it. Isn't it an anti-pattern to call another method first to test this method?
This is exactly how I would do it, so I'm going to vote "no, it is not an anti-pattern".
One thing to notice here, is that in your testing of isVarListSizeFive
you are also necessarily invoking your constructor (either directly within the test, or indirectly via some fixture).
It's probably more appropriate to understand the state machine as your unit (test subject), rather than trying to partition it into multiple units.
Alternative spelling: a dogmatically constrained "unit test" is not necessarily the right tool to investigate mistakes that have been introduced in this code.
As a thought experiment, consider this implementation of SpecialList::add
void addVar(int i) {
// varList.add(i);
}
Clearly, the code is broken. Furthermore, it's broken in a way that should be really easy to catch with automated checks.
But if our rule is that a "unit test" can only include one method, then you are left with a choice of either inadequate coverage or encapsulation violating inspection of the implementation details.
An alternative might be to change your design, so that you can get at the thing you really want to test without the baggage in the way.
Here, that might look like:
class SpecialList {
private List<Integer> varList;
SpecialList() {
varList = new ArrayList<>();
}
void addVar(int i) {
varList.add(i);
}
boolean isVarListSizeFive() {
return isVarListSizeFive(this.varList);
}
// This might want a different name
// and an argument type that isn't mutable.
static boolean isVarListSizeFive(List<Integer> varList) {
if (varList.length() == 5) {
return true;
}
return false;
}
}
In this design, you can write checks against your SizeFive logic without jumping through the hoops of creating and manipulating a SpecialList first.
Complicated code should be easy to test.
Another alternative would be to treat the varList as a sort of collaborator
class SpecialList {
private List<Integer> varList;
SpecialList() {
this(new ArrayList<>());
}
SpecialList(List<Integer> varList) {
this.varList = varList;
}
Now you can invoke methods on SpecialList, and measure their effect using your handle to the same data structure.
Isn't it an anti-pattern to call another method first to test this method?
-- Where did you hear that? Given the current design of the class, I don't see any other way to test it. Do you?