我正在尝试使用方法级安全 Controller 为 Spring-Boot 应用程序设置 RestAssured 测试。
例如,我有一个使用方法级安全性的最小 Controller
@RestController
public class DummyController {
@GetMapping("/")
@PreAuthorize("hasRole('TEST')") // removing this should make the test green
public String test() {
return "hello";
}
}
和宽松的安全配置
@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 未填充。但是...为什么?
最佳答案
所以我终于弄清楚出了什么问题。这是我发现的:
注入(inject) 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(); } }
可以工作,但它只是一个单元测试。
使测试成为正确的集成测试。这将涉及构建适当的身份验证,并配置测试请求的主体,以便 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()); }
关于java - 如何将 Spring SecurityContext 传递给 RestAssured,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50264002/