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
相关产品推荐
相关产品推荐

