You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Boot中如何用TestRestTemplate测试401未授权响应?

Spring Boot中TestRestTemplate测试401未授权场景的正确方式

问题原因

TestRestTemplate底层依赖的RestTemplate默认会将4xx、5xx这类状态码判定为错误请求,直接抛出HttpClientErrorException或ResourceAccessException,导致你无法直接获取响应对象来检查状态码。

解决方案

方法1:修改错误处理器,允许所有状态码

通过自定义ResponseErrorHandler,让RestTemplate不把401视为错误,这样就能正常返回响应对象。如果是使用@Autowired的TestRestTemplate,可以在测试类中重新配置它的错误处理器:

import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.http.client.DefaultResponseErrorHandler;
import org.springframework.http.HttpStatus;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.HttpEntity;
import org.springframework.http.ResponseEntity;
import static org.junit.jupiter.api.Assertions.assertEquals;

@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
class JwtControllerIntegrationTest {

    @Autowired
    private TestRestTemplate testRestTemplate;

    @BeforeEach
    void setUp() {
        // 替换默认错误处理器,不将任何状态码视为错误
        testRestTemplate.getRestTemplate().setErrorHandler(new DefaultResponseErrorHandler() {
            @Override
            protected boolean hasError(HttpStatus statusCode) {
                return false;
            }
        });
    }

    @Test
    void testInvalidCredentialsReturns401() {
        // 构造错误的请求体(替换为你的实际请求DTO)
        AuthRequest wrongAuth = new AuthRequest("invalid-user", "wrong-pass");
        HttpEntity<AuthRequest> request = new HttpEntity<>(wrongAuth);

        // 发送请求并获取响应
        ResponseEntity<String> response = testRestTemplate.postForEntity("/authentications", request, String.class);

        // 验证状态码
        assertEquals(HttpStatus.UNAUTHORIZED, response.getStatusCode());
    }
}

方法2:捕获异常并验证状态码

如果你不想修改全局错误处理器,可以主动捕获TestRestTemplate抛出的HttpClientErrorException,从异常中提取状态码进行验证:

import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpStatus;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.web.client.HttpClientErrorException;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.fail;

@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
class JwtControllerIntegrationTest {

    @Autowired
    private TestRestTemplate testRestTemplate;

    @Test
    void testInvalidCredentialsThrows401() {
        AuthRequest wrongAuth = new AuthRequest("invalid-user", "wrong-pass");
        HttpEntity<AuthRequest> request = new HttpEntity<>(wrongAuth);

        try {
            testRestTemplate.postForObject("/authentications", request, String.class);
            // 如果没抛出异常,测试失败
            fail("Expected HttpClientErrorException for invalid credentials");
        } catch (HttpClientErrorException e) {
            // 验证异常中的状态码
            assertEquals(HttpStatus.UNAUTHORIZED, e.getStatusCode());
        }
    }
}

方法3:使用exchange方法自定义请求配置

使用exchange方法时,可以更灵活地配置请求,包括指定临时的错误处理器,避免影响全局配置:

import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.http.client.DefaultResponseErrorHandler;
import org.springframework.http.HttpStatus;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.client.RestTemplate;
import static org.junit.jupiter.api.Assertions.assertEquals;

@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
class JwtControllerIntegrationTest {

    @Autowired
    private TestRestTemplate testRestTemplate;

    @Test
    void testInvalidCredentialsWithExchange() {
        AuthRequest wrongAuth = new AuthRequest("invalid-user", "wrong-pass");
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        HttpEntity<AuthRequest> request = new HttpEntity<>(wrongAuth, headers);

        // 创建临时的RestTemplate实例,自定义错误处理器
        RestTemplate customRestTemplate = new RestTemplate();
        customRestTemplate.setErrorHandler(new DefaultResponseErrorHandler() {
            @Override
            protected boolean hasError(HttpStatus statusCode) {
                return false;
            }
        });
        TestRestTemplate customTestRestTemplate = new TestRestTemplate(customRestTemplate);

        ResponseEntity<String> response = customTestRestTemplate.exchange(
                "/authentications",
                HttpMethod.POST,
                request,
                String.class
        );

        assertEquals(HttpStatus.UNAUTHORIZED, response.getStatusCode());
    }
}

注意事项

  • 若使用Spring Boot 3.x,上述代码逻辑依然适用,仅部分包路径可能略有调整。
  • 方法1会修改当前TestRestTemplate的全局错误处理行为,如果其他测试用例需要默认的错误抛出逻辑,可在@AfterEach中恢复默认处理器。

内容的提问来源于stack exchange,提问作者Gustavo Ulises Arias Méndez

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 09:58:25