A flaky test is a test that sometimes passes and sometimes fails without any change to the code. Flaky tests are dangerous because they erode trust in the entire test suite — when developers see a red build, they think “probably just a flaky test” and ignore it, and one day that ignored red build is a real regression. This guide identifies every major root cause of flaky JUnit 6 tests and provides permanent, proven fixes for each one.
Why Flaky Tests Are Worse Than No Tests
A test that always fails is a clearly broken test — it gets fixed immediately. A test that occasionally fails trains your team to ignore failures. Once the team stops trusting the test suite, they stop acting on it, which defeats the entire purpose of automated testing. Zero tolerance for flaky tests is the correct policy.
Root Cause 1: Shared Mutable State
This is the most common cause. When tests share mutable state — a static field, a database row, a file on disk — the result depends on which test ran first.
// FLAKY: static counter shared across all test instances
private static int requestCounter = 0;
@Test
void firstRequestIncreasesCounterToOne() {
service.processRequest();
requestCounter++;
assertEquals(1, requestCounter); // FLAKY if other tests also increment
}
// FIX: reset state before each test with @BeforeEach
private int requestCounter; // instance field, NOT static
@BeforeEach
void resetCounter() {
requestCounter = 0; // fresh state for every test, guaranteed
service.reset(); // also reset the service under test
}
@Test
void firstRequestIncreasesCounterToOne() {
service.processRequest();
requestCounter++;
assertEquals(1, requestCounter); // always passes: counter starts at 0
}

