I have created a service with Spring Boot and Reactor. I try to test with Cucumber. POM file (extract):
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.6.2</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.projectreactor</groupId>
<artifactId>reactor-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
<scope>test</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/io.cucumber/cucumber-java -->
<dependency>
<groupId>io.cucumber</groupId>
<artifactId>cucumber-java</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.cucumber</groupId>
<artifactId>cucumber-spring</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.cucumber</groupId>
<artifactId>cucumber-junit-platform-engine</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.platform</groupId>
<artifactId>junit-platform-suite</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.platform</groupId>
<artifactId>junit-platform-console</artifactId>
<scope>test</scope>
</dependency>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>io.cucumber</groupId>
<artifactId>cucumber-bom</artifactId>
<version>7.10.1</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.junit</groupId>
<artifactId>junit-bom</artifactId>
<version>5.9.1</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
My cucumber configuration looks like this:
@Suite
class CucumberTestRunner
@CucumberContextConfiguration
@ContextConfiguration(classes = [CucumberBootstrap::class])
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = [MyApplication::class])
class CucumberSpringContextConfig
@ComponentScan("com.mypackage")
@Configuration
class CucumberBootstrap
The step definition I'm working on is like this:
@ScenarioScope
class MyTestStepDefs(
private val service: MyService
) {
@Given("User is authenticated")
fun userIsAuthenticated() {
val auth = UsernamePasswordAuthenticationToken(
User("username", "password", emptyList()),
"credentials",
emptyList<GrantedAuthority>()
)
val context = ReactiveSecurityContextHolder.getContext().block()
//ReactiveSecurityContextHolder.getContext()
// .doOnNext { it.authentication = auth }
// .block()
}
...
}
I would like to set the authenticated user into the security context. But unfortunately, the security context is always null
.
I have also regular Springt Boot Tests running, where the security context is correctly returned. Here is an extract:
@SpringBootTest(webEnvironment = RANDOM_PORT)
@Transactional(propagation = Propagation.NOT_SUPPORTED)
class MyControllerTests @Autowired constructor(
private val client: WebTestClient
) {
@Test
@WithMockUser
fun `post instruction set`() {
val context = ReactiveSecurityContextHolder.getContext().block()
...
}
...
}
The service class is injected correctly into the step definitions class.
Does anyone have a hint what's missing in the configuration?
Thanks in advance for your help!
Based on M.P. Korstanje's description, I implemented the step as follows:
@Given("User is authenticated")
fun userIsAuthenticated() {
val auth = UsernamePasswordAuthenticationToken(
User("username", "password", emptyList()),
"credentials",
emptyList<GrantedAuthority>()
)
val context = TestSecurityContextHolder.getContext()
context.authentication = auth
val newContext = ReactiveSecurityContextHolder.getContext().block()
assertEquals(auth, newContext?.authentication, "Wrong authentication stored in security context")
}