Cucumber JVM parallel execution: hook thread-affinity guarantee for scenario-scoped @Before/@After
0 reputation · 26 May 2024, 13:52 UTC
0 reputation · 26 May 2024, 13:52 UTC
When running Cucumber JVM scenarios in parallel via JUnit 5's parallel execution or Cucumber's --threads option, reliable management of thread-local resources such as WebDriver instances or database connections depends on whether @Before and @After hooks execute on the same thread as their associated scenario. The current documentation does not explicitly guarantee this thread affinity, leaving a gap for teams that rely on thread-local storage for scenario-scoped state.
Behavior may differ between Cucumber 6.x and 7.x series, and JUnit 5 parallel modes (SAME_THREAD vs CONCURRENT) interact with Cucumber's internal executor in ways that are not fully specified. Custom thread pools or executor services can further alter hook threading unpredictably. Users have also reported inconsistent hook execution order when multiple glue classes define hooks with identical order values under parallel execution.
Without a documented guarantee, teams cannot confidently design cleanup logic that assumes the hook runs on the scenario's thread, risking resource leaks or cross-scenario contamination.
@Before and @After hooks execute on the same thread as the scenario body?32275 reputation · 26 May 2024, 14:12 UTC
Cucumber JVM does not provide a formal, documented guarantee that scenario-scoped @Before and @After hooks execute on the same thread as the scenario body during parallel execution. While this behavior is often observed in sequential runs or specific legacy configurations, relying on this affinity for ThreadLocal resource management is unsafe.
The behavior varies based on the version of Cucumber and the JUnit 5 execution mode used:
SAME_THREAD: Attempts to keep execution within a shared thread, but this does not override Cucumber's internal hook dispatcher logic.CONCURRENT: Explicitly allows parallel execution, where the likelihood of hooks and scenario bodies being assigned to different threads from a pool is significantly higher.Because there is no supported mechanism to enforce or query hook thread affinity, you should avoid ThreadLocal for scenario-scoped state. Instead, use the following patterns:
To verify the actual behavior in your specific environment, implement a thread-logging check:
@Before
public void logBefore() {
System.out.println("Before Hook Thread: " + Thread.currentThread().getName());
}
@Then("I verify thread affinity")
public void verifyThread() {
System.out.println("Scenario Step Thread: " + Thread.currentThread().getName());
}
@After
public void logAfter() {
System.out.println("After Hook Thread: " + Thread.currentThread().getName());
}
Run your tests with --threads 2 (or your JUnit 5 parallel config). If the thread names differ between the hook and the step, your environment does not maintain thread affinity.
Diagnostic Note: To provide a more tailored recommendation, please specify if you are using a custom ExecutorService or a specific DI framework (e.g., Spring) for your glue code.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.