Annotation Interface ForkedJvm
Useful for testing behaviour gated by JVM startup state that cannot be
toggled at runtime, e.g. static final fields initialised from
System.getProperty(...) at class load time
(such as groovy.val.enabled).
System properties are supplied as "key=value" strings:
@Test
@ForkedJvm(systemProperties = {"groovy.val.enabled=false"})
void runsInChildJvm() {
assert System.getProperty("groovy.val.enabled").equals("false");
}
JVM arguments are passed verbatim:
@Test
@ForkedJvm(jvmArgs = {"--add-opens=java.base/java.lang=ALL-UNNAMED"})
void withModuleAccess() { ... }
Recipe — @GrabConfig(systemClassLoader=true) tests:
scripts that use @GrabConfig(systemClassLoader=true) to add
resolved JARs to the JVM system classloader only behave
correctly when that classloader is Groovy's RootLoader, which
cannot be retrofitted after JVM startup. Set it via jvmArgs:
@Test
@ForkedJvm(jvmArgs = {"-Djava.system.class.loader=org.codehaus.groovy.tools.RootLoader"})
void scriptUsesGrabConfigSystemClassLoader() {
assertScript '''
@GrabConfig(systemClassLoader=true)
@Grab('org.example:some-lib:1.0')
// ... library is now visible to anything resolving via the system classloader ...
'''
}
Properties from the parent JVM can be propagated to the child via
inheritProperties(). Each entry is either an exact property
name or a prefix pattern ending in *. This is useful when the
parent test JVM is configured by the build (e.g. Gradle) with a
property the child also needs, such as Spock's Groovy-version-check
override:
@Test
@ForkedJvm(inheritProperties = {"spock.*"})
void seesSpockOverride() { ... }
Lifecycle gotcha: JUnit lifecycle hooks
(@BeforeAll, @BeforeEach, @AfterAll,
@AfterEach) fire in both the parent and the forked
child JVM, because the child re-runs the class lifecycle for the
targeted method. Setup that mutates JVM-global state — typically
System.setProperty(...) — therefore replays in the child and
can defeat tests that assert on what was (or was not) propagated
across the fork. Guard parent-only setup with the forked-flag check:
@BeforeAll
static void setUp() {
if (Boolean.parseBoolean(System.getProperty("groovy.junit6.forked"))) return;
// ...parent-only setup here...
}
- Since:
- 6.0.0
-
Optional Element Summary
Optional ElementsModifier and TypeOptional ElementDescriptionString[]Regular expressions that exclude matching entries from the parent'sjava.class.pathwhen constructing the forked JVM's classpath.String[]Names or prefix patterns of system properties from the parent JVM to propagate to the forked child.String[]Raw JVM arguments to prepend to the forked JVM's command line, e.g.String[]System properties to set on the forked JVM, each as a"key=value"string.
-
Element Details
-
systemProperties
String[] systemPropertiesSystem properties to set on the forked JVM, each as a"key=value"string.- Default:
- {}
-
jvmArgs
String[] jvmArgsRaw JVM arguments to prepend to the forked JVM's command line, e.g."-Xmx128m"or"--add-opens=java.base/java.lang=ALL-UNNAMED".- Default:
- {}
-
inheritProperties
String[] inheritPropertiesNames or prefix patterns of system properties from the parent JVM to propagate to the forked child. Each entry is either an exact property name (e.g."spock.iKnowWhatImDoing.disableGroovyVersionCheck") or a prefix pattern ending in*(e.g."spock.*"or"groovy.compiler.*"). Patterns that match no parent property are silently ignored.Properties supplied via
systemProperties()override inherited values for the same key.- Default:
- {}
-
excludeFromClasspath
String[] excludeFromClasspathRegular expressions that exclude matching entries from the parent'sjava.class.pathwhen constructing the forked JVM's classpath. Each pattern is applied to each path entry withMatcher.find(), so plain substrings (e.g."junit-platform-instrumentation") work without anchoring.Patterns can also be supplied via the system property
groovy.junit6.forked.excludeClasspath(comma-separated) for build- or CI-level configuration without modifying test source. Annotation values and the system-property values are unioned.Limitations: this filter only inspects entries appearing literally in
java.class.path. Modules on--module-path, directory wildcards (e.g.lib/*), andClass-Path:manifest entries inherited from another jar are not matched.- Default:
- {}
-