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

如何测试带有@Secured注解且实现接口的Spring Rest Controller?

解决@WebMvcTest无法识别带@Secured注解且实现接口的REST控制器问题

问题概述

当REST控制器同时满足以下两个条件时:

  • 实现了某个接口
  • 类上标注了@Secured注解
    使用@WebMvcTest编写单元测试会出现控制器无法被识别的情况,测试请求返回404状态码。但只要移除@Secured注解,或者让控制器不实现接口,测试就能正常返回200;且实际应用运行时,两种控制器都能被正常识别。

通过注入RequestMappingHandlerMapping可发现,带接口继承关系的控制器并未被绑定到请求映射上,这是测试上下文特有的问题。

可行解决方案

1. 手动注册请求映射到测试上下文

在测试类中,手动将目标控制器的请求映射注册到RequestMappingHandlerMapping中,确保测试上下文能找到对应的处理方法:

@WebMvcTest(FailingTestController.class)
@EnableGlobalMethodSecurity(securedEnabled = true)
class FailingTestControllerTest {

    @Autowired
    private MockMvc mockMvc;

    @Autowired
    private RequestMappingHandlerMapping handlerMapping;

    @Autowired
    private FailingTestController failingTestController;

    @BeforeEach
    void setup() throws NoSuchMethodException {
        // 构建对应请求的映射信息
        RequestMappingInfo mappingInfo = RequestMappingInfo
                .paths("/api/v1/password")
                .methods(HttpMethod.PUT)
                .build();
        // 获取控制器中的处理方法
        Method method = FailingTestController.class.getMethod("updatePassword", String.class);
        // 注册映射
        handlerMapping.registerMapping(mappingInfo, failingTestController, method);
    }

    @Test
    void updatePassword_shouldReturnOk() throws Exception {
        mockMvc.perform(put("/api/v1/password")
                        .param("newPassword", "testPass123"))
                .andExpect(status().isOk());
    }
}

2. 改用完整Spring上下文测试

如果测试需要依赖完整的安全配置或其他上下文组件,可以用@SpringBootTest配合@AutoConfigureMockMvc替代@WebMvcTest,这样能完整加载所有控制器配置:

@SpringBootTest
@AutoConfigureMockMvc
@EnableGlobalMethodSecurity(securedEnabled = true)
class FailingTestControllerTest {

    @Autowired
    private MockMvc mockMvc;

    @Test
    void updatePassword_shouldReturnOk() throws Exception {
        mockMvc.perform(put("/api/v1/password")
                        .param("newPassword", "testPass123"))
                .andExpect(status().isOk());
    }
}

3. 调整@Secured注解的位置

将@Secured注解从类级别移到具体的请求处理方法上,部分场景下可以触发测试上下文正确绑定请求映射:

@RestController
public class FailingTestController implements MyPasswordApi {

    @Override
    @Secured("ROLE_USER")
    @PutMapping("/api/v1/password")
    public ResponseEntity<Void> updatePassword(@RequestParam String newPassword) {
        // 业务逻辑实现
        return ResponseEntity.ok().build();
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 17:55:20