Skip to content

Commit 9e23ce9

Browse files
committed
[Spring] Document scenario scope is proxied
Closes: #2647
1 parent 98c338d commit 9e23ce9

File tree

2 files changed

+71
-1
lines changed

2 files changed

+71
-1
lines changed

cucumber-spring/README.md

+65
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,9 @@ Annotate a field in your step definition class with `@Autowired`.
102102
```java
103103
package com.example.app;
104104

105+
import org.springframework.beans.factory.annotation.Autowired;
106+
import io.cucumber.java.en.Given;
107+
105108
public class MyStepDefinitions {
106109

107110
@Autowired
@@ -162,6 +165,9 @@ The glue scoped component can then be autowired into a step definition:
162165
```java
163166
package com.example.app;
164167

168+
import org.springframework.beans.factory.annotation.Autowired;
169+
import io.cucumber.java.en.Given;
170+
165171
public class UserStepDefinitions {
166172

167173
@Autowired
@@ -194,6 +200,65 @@ public class PurchaseStepDefinitions {
194200
}
195201
```
196202

203+
#### Sharing state between threads
204+
205+
By default, when using `@ScenarioScope` these beans must also be accessed on
206+
the same thread as the one that is executing the scenario. If you are certain
207+
your scenario scoped beans can only be accessed through step definitions you
208+
can use `@ScenarioScope(proxyMode = ScopedProxyMode.NO)`.
209+
210+
211+
```java
212+
package com.example.app;
213+
214+
import org.springframework.stereotype.Component;
215+
import io.cucumber.spring.ScenarioScope;
216+
import org.springframework.context.annotation.ScopedProxyMode;
217+
218+
@Component
219+
@ScenarioScope(proxyMode = ScopedProxyMode.NO)
220+
public class TestUserInformation {
221+
222+
private User testUser;
223+
224+
public void setTestUser(User testUser) {
225+
this.testUser = testUser;
226+
}
227+
228+
public User getTestUser() {
229+
return testUser;
230+
}
231+
232+
}
233+
```
234+
235+
```java
236+
package com.example.app;
237+
238+
import org.springframework.beans.factory.annotation.Autowired;
239+
import io.cucumber.java.en.Given;
240+
import org.awaitility.Awaitility;
241+
242+
public class UserStepDefinitions {
243+
244+
@Autowired
245+
private TestUserInformation testUserInformation;
246+
247+
@Then("the test user is eventually created")
248+
public void a_user_is_eventually_created() {
249+
Awaitility.await()
250+
.untilAsserted(() -> {
251+
// This happens on a different thread
252+
TestUser testUser = testUserInformation.getTestUser();
253+
Optional<User> user = repository.findById(testUser.getId());
254+
assertTrue(user.isPresent());
255+
});
256+
}
257+
}
258+
```
259+
260+
261+
197262
### Dirtying the application context
198263

199264
If your tests do dirty the application context you can add `@DirtiesContext` to

cucumber-spring/src/main/java/io/cucumber/spring/CucumberTestContext.java

+6-1
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,12 @@ void registerDestructionCallback(String name, Runnable callback) {
6868
void requireActiveScenario() {
6969
if (!isActive()) {
7070
throw new IllegalStateException(
71-
"Scenario scoped beans can only be created while Cucumber is executing a scenario");
71+
"Scenario scoped beans can only be accessed while Cucumber is executing a scenario\n" +
72+
"\n" +
73+
"Note: By default, when using @ScenarioScope these beans must also be accessed on the\n" +
74+
"same thread as the one that is executing the scenario. If you are certain your scenario\n" +
75+
"scoped beans can only be accessed through step definitions you can also use\n" +
76+
"@ScenarioScope(proxyMode = ScopedProxyMode.NO)");
7277
}
7378
}
7479

0 commit comments

Comments
 (0)