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

Spring Boot HTTPS改造后测试遇枚举反序列化403错误

问题根源分析

你的测试报错本质是请求实际返回了403 Forbidden状态码,但测试代码未先校验响应状态,直接尝试将响应内容(或错误处理时误把状态码当作枚举值)反序列化为Status枚举。因为Status只有3个枚举值,403超出了枚举的索引范围,所以抛出反序列化错误。

仅GET/JPA测试正常的原因是:GET请求可能被你的Security配置允许匿名访问,而JPA测试直接操作数据库,不涉及HTTP请求,不受Security/HTTPS影响。


解决方案

1. 先验证请求的实际响应状态

在测试代码里先打印响应状态码,确认是否真的返回403:

val response = testRestTemplate.postForEntity("/api/orders", orderRequest, Order::class.java)
println("Response status: ${response.statusCode}") // 输出403则说明请求被Security拦截

2. 修正TestRestTemplate的认证配置

确保测试用的TestRestTemplate携带有效的认证信息,比如:

// 方式1:直接传入用户名密码初始化
val testRestTemplate = TestRestTemplate("test-user", "test-pass")

// 方式2:在测试类中注入后追加认证信息
@Autowired
lateinit var testRestTemplate: TestRestTemplate

@BeforeEach
fun setupAuth() {
    testRestTemplate = testRestTemplate.withBasicAuth("test-user", "test-pass")
}

3. 调整测试代码的响应处理逻辑

不要直接反序列化响应体,先校验状态码是否符合预期:

val response = testRestTemplate.postForEntity("/api/orders", orderRequest, Order::class.java)
// 先断言状态码成功
assertThat(response.statusCode).isEqualTo(HttpStatus.CREATED)
// 再获取响应体做后续校验
val createdOrder = response.body ?: throw AssertionError("Response body is null")
assertThat(createdOrder.status).isEqualTo(Status.IN_PROGRESS)

这样如果返回403,会直接触发断言失败,而不是进入反序列化环节报错。

4. 优化Security测试环境配置

为测试环境单独配置Security,放开必要的端点权限,避免测试被拦截:

@Configuration
@Profile("test")
class TestSecurityConfig {
    @Bean
    fun filterChain(http: HttpSecurity): SecurityFilterChain {
        http
            .authorizeHttpRequests { auth ->
                // 测试环境允许所有请求通过
                auth.anyRequest().permitAll()
            }
            .csrf().disable() // 测试环境可关闭CSRF,方便POST/PUT等请求测试
        return http.build()
    }
}

同时在application-test.properties中指定激活test profile:

spring.profiles.active=test

5. 确认HTTPS测试配置正确性

确保测试环境的HTTPS配置正确,比如在application-test.properties中添加:

server.ssl.enabled=true
server.ssl.key-store=classpath:test-keystore.p12
server.ssl.key-store-password=test123
server.ssl.key-store-type=PKCS12

如果使用自签名证书,可让TestRestTemplate信任该证书(仅测试环境使用):

fun createTestRestTemplate(): TestRestTemplate {
    val sslContext = SSLContextBuilder.create()
        .loadTrustMaterial(null) { _, _ -> true }
        .build()
    val factory = HttpComponentsClientHttpRequestFactory()
    factory.setHttpClient(HttpClients.custom().setSSLContext(sslContext).build())
    return TestRestTemplate(factory)
}

内容的提问来源于stack exchange,提问作者shlfdn

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 22:17:30