1. Overview
In this quick tutorial, we'll learn about the @DirtiesContext annotation. We'll also show a standard way to use the annotation for testing.
2. @DirtiesContext
@DirtiesContext is a Spring testing annotation. It indicates the associated test or class modifies the ApplicationContext. It tells the testing framework to close and recreate the context for later tests.
We can annotate a test method or an entire class. By setting the MethodMode or ClassMode, we can control when Spring marks the context for closure.
If we place @DirtiesContext on a class, the annotation applies to every method in the class with the given ClassMode.
3. Testing Without Clearing the Spring Context
Let's say we have a User:
public class User { String firstName; String lastName; }
We also have a very simple UserCache:
@Component public class UserCache { @Getter private Set<String> userList = new HashSet<>(); public boolean addUser(String user) { return userList.add(user); } public void printUserList(String message) { System.out.println(message + ": " + userList); } }
We create an integration test to load up and test the full application:
@TestMethodOrder(OrderAnnotation.class) @ExtendWith(SpringExtension.class) @SpringBootTest(classes = SpringDataRestApplication.class) class DirtiesContextIntegrationTest { @Autowired protected UserCache userCache; ... }
The first method, addJaneDoeAndPrintCache, adds an entry to the cache:
@Test @Order(1) void addJaneDoeAndPrintCache() { userCache.addUser("Jane Doe"); userCache.printUserList("addJaneDoeAndPrintCache"); }
After adding a user to the cache, it prints the contents of the cache:
addJaneDoeAndPrintCache: [Jane Doe]
Next, printCache prints the user cache again:
@Test @Order(2) void printCache() { userCache.printUserList("printCache"); }
It contains the name added in the previous test:
printCache: [Jane Doe]
Let's say a later test was relying on an empty cache for some assertions. The previously inserted names may cause undesired behavior.
4. Using @DirtiesContext
Now we'll show @DirtiesContext with the default MethodMode, AFTER_METHOD. This means Spring will mark the context for closure after the corresponding test method completes.
To isolate changes to a test, we add @DirtiesContext. Let's see how it works.
The addJohnDoeAndPrintCache test method adds a user to the cache. We have also added the @DirtiesContext annotation, which says the context should shut down at the end of the test method:
@DirtiesContext(methodMode = MethodMode.AFTER_METHOD) @Test @Order(3) void addJohnDoeAndPrintCache() { userCache.addUser("John Doe"); userCache.printUserList("addJohnDoeAndPrintCache"); }
The output is now:
addJohnDoeAndPrintCache: [John Doe, Jane Doe]
Finally, printCacheAgain prints the cache again:
@Test @Order(4) void printCacheAgain() { userCache.printUserList("printCacheAgain"); }
Running the full test class, we see the Spring context reload in between addJohnDoeAndPrintCache and printCacheAgain. So the cache reinitializes, and the output is empty:
printCacheAgain: []
5. Other Supported Test Phases
The example above shows the after current test method phase. Let's do a quick summary of the phases:
5.1. Class Level
The ClassMode options for a test class define when the context is reset:
- BEFORE_CLASS: Before current test class
- BEFORE_EACH_TEST_METHOD: Before each test method in the current test class
- AFTER_EACH_TEST_METHOD: After each test method in the current test class
- AFTER_CLASS: After the current test class
5.2. Method Level
The MethodMode options for an individual method define when the context is reset:
- BEFORE_METHOD: Before the current test method
- AFTER_METHOD: After the current test method
6. Conclusion
In this article, we presented the @DirtiesContext testing annotation.
As always, the example code is available over on GitHub.