use*_*011 4 java testing spring-security rest-assured spring-boot
我正在尝试为具有方法级安全控制器的 Spring-Boot 应用程序设置 RestAssured 测试。
例如,我有一个使用方法级安全性的最小控制器
@RestController
public class DummyController {
@GetMapping("/")
@PreAuthorize("hasRole('TEST')") // removing this should make the test green
public String test() {
return "hello";
}
}
Run Code Online (Sandbox Code Playgroud)
和宽松的安全配置
@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().anyRequest().permitAll();
}
}
然后使用 RestAssured 的这个简单测试失败了:
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@RunWith(SpringRunner.class)
public class DummyControllerITest {
private static final Logger logger = LoggerFactory.getLogger(DummyControllerITest.class);
@LocalServerPort
private int port;
@Test
@WithMockUser(roles = "TEST")
public void name() throws Exception {
RestAssured.given()
.port(port)
.when()
.get("/")
.then()
.statusCode(HttpStatus.OK.value());
}
}
即使模拟用户配置了正确的角色,为什么此测试仍会失败?
我已经对此进行了调试,似乎运行测试的线程中的 SecurityContext 设置正确,而处理 RestAssured 请求的线程中的 SecurityContext 未填充。但为什么?
所以我终于明白出了什么问题。这是我发现的:
注入 SecurityContext 仅在单元测试中有意义,但原始测试试图成为集成测试。
有两种出路:
使测试成为适当的单元测试。那么你应该使用RestAssuredMockMvc.given()
而不是RestAssured.given()
. 例如,
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.MOCK)
@RunWith(SpringRunner.class)
public class DummyControllerITest {
@Autowired
private WebApplicationContext webAppContextSetup;
@Test
@WithMockUser(roles = "TEST")
public void name() throws Exception {
RestAssuredMockMvc.webAppContextSetup(webAppContextSetup);
RestAssuredMockMvc.given()
.when()
.get("/")
.then()
.statusCode(HttpStatus.OK.value());
RestAssuredMockMvc.reset();
}
}
Run Code Online (Sandbox Code Playgroud)
会起作用,但那时它只是一个单元测试。
使测试成为适当的集成测试。这将涉及构建正确的身份验证,并配置测试请求的主体,以便根据生产代码的需要填充 SecurityContext 。与 RestAssured 一起走这条路看起来会像这样:
@Test
@WithMockUser(roles = "TEST")
public void name() throws Exception {
given()
.auth().basic("testuser", "password") // ######
.port(port)
.when()
.get("/")
.then()
.statusCode(HttpStatus.OK.value());
}
Run Code Online (Sandbox Code Playgroud) 归档时间: |
|
查看次数: |
4292 次 |
最近记录: |