Two member-saving tests pass separately. Run them together, and the second throws duplicate: kim. Before blaming test order, look for state the tests share. A static in-memory repository can keep data even when each test constructs a new repository object.
Why can in-memory repository tests affect one another?
During early development, a Map may stand in for a database. Here store is static, so two new MemoryRepository() calls still refer to one storage area:
import java.util.HashMap;
import java.util.Map;
class MemoryRepository {
private static final Map<String, Integer> store = new HashMap<>();
void save(String name) {
if (store.containsKey(name)) {
throw new IllegalStateException("duplicate: " + name);
}
store.put(name, store.size() + 1);
}
int count() { return store.size(); }
void clear() { store.clear(); }
}If the first test saves kim and does not clear the map, the next test sees the same key. new makes another object; it does not recreate its class's static field.
The diagram shows the shared static store. Clearing that store after a test removes this example's leftover kim, although separate storage is often the better design.
Why does another new object still detect a duplicate?
Run the operations in order:
class Demo {
public static void main(String[] args) {
MemoryRepository first = new MemoryRepository();
first.save("kim");
System.out.println(first.count());
MemoryRepository second = new MemoryRepository();
try {
second.save("kim");
} catch (IllegalStateException error) {
System.out.println(error.getMessage());
}
first.clear();
second.save("kim");
System.out.println(second.count());
}
}1
duplicate: kim
1The second save throws before cleanup; after cleanup, that name can be saved again. By default, JUnit Jupiter creates a fresh test-class instance per test method, but this does not reset unrelated static fields. JUnit documents its test-instance lifecycle.
What should @AfterEach clear?
When a shared store is required for this example, clear it after each test so the next test starts without earlier data:
import static org.junit.jupiter.api.Assertions.assertEquals;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Test;
class MemoryRepositoryTest {
private final MemoryRepository repository = new MemoryRepository();
@AfterEach
void tearDown() {
repository.clear();
}
@Test
void savesMember() {
repository.save("kim");
assertEquals(1, repository.count());
}
@Test
void alsoStartsEmpty() {
repository.save("kim");
assertEquals(1, repository.count());
}
}@AfterEach runs after each JUnit Jupiter test. With serial execution and no other users of this static map, the cleanup prevents one test's kim from affecting the next.
When is clear() insufficient?
If possible, remove static and give each test its own repository instance. That avoids interference when a cleanup call is forgotten. If a Spring context shares a bean or tests use a real database, inspect which resources are actually shared.
In parallel tests, one test's clear() can erase another test's data, so @AfterEach alone does not guarantee isolation. Design separate stores, distinct test keys, or suitable database transaction boundaries. Do not copy a blanket clear() operation from an in-memory example into a production data store.
Key takeaways
If tests fail only when run together, look for state surviving between them. A static repository store is shared even across newly constructed objects. @AfterEach can clean up this serial example, but independent storage per test is usually the clearer starting point.

