When running tests using @DirtiesContext and a test class includes multiple @Nested classes, the context is dirtied and refreshed after each nested class, even when using the coarsest mode possible level (ClassMode.AFTER_CLASS).

There is currently no way to specify that @DirtiesContext should only dirty the context after the top-level class but not after each nested class.

A ClassMode.AFTER_MAIN_CLASS is suggested to specify the desired functionality.

Comment From: nithril

Would be nice indeed to get control and optimize test execution

Comment From: sbrannen

Hi @jmarchionatto,

Thanks for the proposal, and apologies for not getting to this earlier.

If we were to introduce this support specifically for @Nested test classes, I'd rather name the new ClassMode AFTER_ENCLOSING_CLASS.

However, I investigated our options, and it appears that it might be easier to introduce ClassMode.DISABLED which could be applied to individual @Nested test classes. In theory, that approach should also allow ClassMode.DISABLED to be used on subclasses within a type hierarchy.

In light of that, I've scheduled this for 6.2 M1.

Comment From: jmarchionatto

Sounds good, @sbrannen . Thank you

Comment From: sbrannen

If we were to introduce this support specifically for @Nested test classes, I'd rather name the new ClassMode AFTER_ENCLOSING_CLASS.

After furthering experimentation, this new mode would need to be called AFTER_TOP_LEVEL_CLASS to signal that the context would only be dirtied after the top-level enclosing class for all @Nested test classes.

In other words, the AFTER_TOP_LEVEL_CLASS mode would not apply to the immediately enclosing class for a @Nested test class nested in another @Nested test class.

I currently tend to prefer AFTER_TOP_LEVEL_CLASS over DISABLED since DISABLED would have to be applied to every @Nested class declared directly under a class annotated with @DirtiesContext; whereas, @DirtiesContext(classMode = AFTER_TOP_LEVEL_CLASS) would be inherited by all @Nested test classes that do not override it with a local @DirtiesContext declaration.

I'm sure the "devil is in the details." 😈

But, a quick prototype reveals that it may be as simple as:

  1. Creating the AFTER_TOP_LEVEL_CLASS enum constant in ClassMode.
  2. Adding the following logic to AbstractDirtiesContextTestExecutionListener.beforeOrAfterTestClass(...).
if (classMode == ClassMode.AFTER_TOP_LEVEL_CLASS && !ClassUtils.isInnerClass(testClass)) {
    classMode = ClassMode.AFTER_CLASS;
}

The idea behind the above is that it effectively ignores @DirtiesContext on a @Nested test class and coverts the class mode to AFTER_CLASS for the top-level enclosing class.