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

如何根据测试注解为MockMvc请求自动添加Authorization请求头?

自动为带@WithJwt注解的测试方法添加Authorization请求头

我来给你拆解一下实现这个需求的方案,核心是借助Spring Test的测试上下文和MockMvc的请求后置处理器,让带有@WithJwt注解的测试方法自动注入Authorization请求头,不用每次手动编写.header()代码。

步骤1:自定义JWT授权请求后置处理器

首先我们需要一个RequestPostProcessor,它能识别当前测试方法是否带有@WithJwt注解,并自动添加对应的请求头。这里我们通过TestContextManager获取当前执行的测试方法信息:

import org.springframework.test.context.TestContextManager;
import org.springframework.test.web.servlet.RequestPostProcessor;
import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;

public class JwtAuthRequestPostProcessor implements RequestPostProcessor {

    private final TestContextManager testContextManager;

    public JwtAuthRequestPostProcessor(TestContextManager testContextManager) {
        this.testContextManager = testContextManager;
    }

    @Override
    public HttpServletRequest postProcessRequest(HttpServletRequest request) {
        try {
            // 获取当前正在执行的测试方法
            Method testMethod = testContextManager.getTestContext().getTestMethod();
            WithJwt withJwt = testMethod.getAnnotation(WithJwt.class);
            
            if (withJwt != null) {
                // 这里可以根据@WithJwt的属性动态生成JWT,示例用固定值"Bearer foo"
                String jwtToken = "Bearer foo";
                request.addHeader("Authorization", jwtToken);
            }
        } catch (Exception e) {
            throw new RuntimeException("Failed to add JWT authorization header", e);
        }
        return request;
    }
}

步骤2:在测试类中配置MockMvc

接下来不要直接依赖@Autowired注入的MockMvc,而是手动构建MockMvc并添加我们自定义的后置处理器。同时注入TestContextManager来传递测试上下文信息:

@RunWith(SpringRunner.class)
@EnableSpringDataWebSupport
@WebMvcTest(MyController.class)
@Import({WebSecurityConfig.class})
public class MyControllerTest {

    @Autowired
    private WebApplicationContext webApplicationContext;

    @Autowired
    private TestContextManager testContextManager;

    protected MockMvc mockMvc;

    @BeforeEach
    public void setup() {
        this.mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext)
                // 添加全局请求后置处理器
                .defaultRequest(new JwtAuthRequestPostProcessor(testContextManager))
                .build();
    }

    @Test
    @WithJwt(principal = "admin", authorities = {"READ_USERS"})
    public void readUsersAuthorityCanListUsers() throws Exception {
        final List<User> users = Arrays.asList(admin, user);
        when(userRepo.findAll(any(Pageable.class))).thenReturn(new PageImpl<>(users));
        
        // 这里不需要手动添加Authorization头了!
        this.mockMvc
                .perform(get("/"))
                .andExpect(status().isOk())
                .andExpect(jsonPath("$.content", hasSize(users.size())));
    }

    @Test
    // 没有@WithJwt注解,不会自动添加Authorization头
    public void unauthenticatedRequestShouldFail() throws Exception {
        this.mockMvc
                .perform(get("/"))
                .andExpect(status().isUnauthorized());
    }
}

步骤3:封装成可复用的MockMvc配置器(可选)

如果多个测试类都需要这个功能,我们可以把逻辑封装成MockMvcConfigurer,方便复用:

import org.springframework.test.context.TestContextManager;
import org.springframework.test.web.servlet.MockMvcConfigurer;
import org.springframework.test.web.servlet.config.ConfigurableMockMvcBuilder;

public class JwtAuthMockMvcConfigurer implements MockMvcConfigurer {

    private final TestContextManager testContextManager;

    public JwtAuthMockMvcConfigurer(TestContextManager testContextManager) {
        this.testContextManager = testContextManager;
    }

    @Override
    public void afterConfigurerAdded(ConfigurableMockMvcBuilder<?> builder) {
        builder.defaultRequest(new JwtAuthRequestPostProcessor(testContextManager));
    }
}

然后在测试类的setup方法中使用:

@BeforeEach
public void setup() {
    this.mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext)
            .apply(new JwtAuthMockMvcConfigurer(testContextManager))
            .build();
}

进阶:动态生成JWT Token

如果你的@WithJwt注解的principal和authorities是用来生成真实JWT的,可以在处理器中根据注解属性动态生成token,比如:

if (withJwt != null) {
    // 假设你有一个JwtTokenUtil工具类来生成token
    String jwtToken = "Bearer " + jwtTokenUtil.generateToken(withJwt.principal(), withJwt.authorities());
    request.addHeader("Authorization", jwtToken);
}

注意事项

  • 确保TestContextManager能被正确注入,Spring Test会自动管理这个bean,直接用@Autowired即可。
  • 如果之前依赖自动配置的MockMvc,需要改为手动构建才能添加自定义处理器。
  • 全局后置处理器会作用于所有请求,但只有带有@WithJwt注解的测试方法才会添加Authorization头,不会影响其他测试。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 06:44:42