java - 如何将 Spring SecurityContext 传递给 RestAssured

标签 java spring-boot testing spring-security rest-assured

我正在尝试使用方法级安全 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 仅在单元测试中有意义,但原始测试试图成为集成测试。

有两种方法:

  1. 使测试成为正确的单元测试。那么您应该使用 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();
      }
    }
    

    可以工作,但它只是一个单元测试。

  2. 使测试成为正确的集成测试。这将涉及构建适当的身份验证,并配置测试请求的主体,以便 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/

相关文章:

java - 如何从 Android 后台线程更新 UI 元素?

spring-boot - SpringBoot + Rabbitmq - DLQ 队列不工作

Spring Boot 2.0 无法使用 Caffeine 作为缓存提供程序

linux - 使用反向代理记录所有传入的 HTTP 请求,然后在克隆服务器中执行它以进行性能测试

java - Spring Web Service REST API JSON 响应始终包含 boolean 值

java - 丢失后回收多米诺骨牌对象

java - 如何为 Spring Boot 应用程序执行命令行任务(如 Rake 任务)?

testing - JUnit 使用 Spring MVC 测试 web.xml

testing - 苹果商店还没有的IOS App的崩溃报告如何查看?

java - 如何处理大型 csv 文件