首页 > 解决方案 > 在 Spring Boot 的集成测试期间模拟 rest api 调用

问题描述

我有一个 Spring Boot 服务,它通过调用我的身份验证服务来验证每个请求。现在我正在编写一个集成测试。如何在测试自己的 API 时模拟对身份验证服务的请求?

@GetMapping("/pending/task")
    @Operation(summary = "Get user's pending task", tags = "UserTask", security = {@SecurityRequirement(name = Constants.AUTH_TOKEN_HEADER)})
    @PreAuthorize(Constants.PreAuthorize.ROLE)
    public List<UserTaskDto> getPendingTasks(@Valid @RequestParam long courseId){
        // internal logic
    }
SpringBoot filter will read the token from the header and verify that against auth service using rest. I want to mock that call during this api testing.

测试代码

class UserTaskControllerTest extends ApplicationTests {

@Mock
RestTemplate restTemplate;

@Test
void shouldGiveAllUserPendingTask(){
    HttpHeaders headers = new HttpHeaders();
    headers.add(Constants.AUTH_TOKEN_HEADER, GENERIC_AUTH_TOKEN);
    Task task = FactoryClass.createTask();
    UserTask userTask = FactoryClass.createUserTask();
    CentralAuthInfo centralAuthInfo = FactoryClass.getCentralAuthInfo();
    taskRepository.save(task);
    userTask.setTask(task);
    userTaskRepository.save(userTask);
    UriComponentsBuilder builder = UriComponentsBuilder.fromUriString(USER_PENDING_TASK_BASE_URL)
            .queryParam(COURSE_ID, userTask.getCohortId());

    when(restTemplate.exchange(ArgumentMatchers.anyString(), ArgumentMatchers.any(HttpMethod.class), ArgumentMatchers.any(HttpEntity.class), ArgumentMatchers.eq(CentralAuthInfo.class))).thenReturn(new ResponseEntity<>(centralAuthInfo, HttpStatus.OK));
    ResponseEntity<UserTaskDto> responseEntity = testRestTemplate.exchange(builder.toUriString(), GET, new HttpEntity<>(headers), UserTaskDto.class);
    assertThat(responseEntity.getStatusCode()).isEqualTo(200);
}

标签: spring-bootjunit5spring-test

解决方案


Spring 提供了一个@WithMockUser可以添加到测试中的方法。我通常使用它WebTextClient来测试 API 调用。这是一个反应式控制器的例子,但同样适用于非反应式

@Import(SecurityConfig.class)
@WebFluxTest(MyController.class)
class MyControllerTest {
    @Autowired
    private WebTestClient webTestClient;
...
    @Test
    @WithMockUser(username="admin",roles={"USER","ADMIN", "ROLE"})
    void testPendingTasks() {
        webTestClient
                .get()
                .uri("/pending/task")
                .exchange()
                .expectStatus()
                .isOk();
    }
...
}

推荐阅读