Unannotated Test Lifecycle Hook
ID |
java.junit3_override_setup |
Severity |
high |
Remediation Complexity |
trivial |
Remediation Risk |
low |
Remediation Effort |
low |
Resource |
Reliability |
Language |
Java |
Tags |
best-practice, junit, testing |
Description
| Disabled by default. The rule reports that the hook "will never run", which is false whenever the overriding method calls it explicitly — the majority of real findings. Repairing it needs method-symbol resolution the rule does not have. |
Reports a setUp or tearDown method in an annotation-driven test class — one that has JUnit 4 or JUnit 5 test methods — which carries no matching lifecycle annotation.
Rationale
JUnit 3 recognised setUp and tearDown by name and ran them around every test. JUnit 4 and JUnit 5 do not: they run whatever is annotated, and a method named setUp means nothing to them.
This makes the defect unusually quiet. The class still compiles, the test methods still run, and they pass — but they run against whatever state the fields happened to have, because the setup never executed. Nothing fails until a test starts depending on that setup, at which point the failure appears far from its cause.
public class LedgerBalanceTest {
private LedgerBook book;
public void setUp() { // never called by JUnit 4 or JUnit 5
book = new LedgerBook();
}
@Test
public void balanceStartsAtZero() {
assertEquals(0, book.balance()); // NullPointerException, not a clear failure
}
}
Remediation
Annotate the hook with the lifecycle annotation of the JUnit version in use, or — if the method was never meant to be a hook — rename it so it does not read like one.
public class LedgerBalanceTest {
private LedgerBook book;
@BeforeEach // @Before on JUnit 4
public void setUp() {
book = new LedgerBook();
}
@Test
public void balanceStartsAtZero() {
assertEquals(0, book.balance());
}
}
What is not reported
A class extending junit.framework.TestCase is left alone: JUnit 3 still drives the hooks by name there, so no annotation is wanted. Nor is a class without any test method, an overload taking arguments, a private method the framework could not call, or a method marked @Override that inherits its annotation from the parent it overrides.