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

Spring Authorization Server的JUnit 5测试遇404问题求助

问题

为Spring Authorization Server编写JUnit 5测试用例时,请求/oauth2/token端点返回404错误,日志显示请求被映射到静态资源处理器,提示找不到对应资源;但使用Postman携带相同参数请求该端点却能成功完成授权。请问该端点未监听请求的原因是什么,该如何解决此问题?

测试代码

import org.junit.jupiter.api.Test;
import org.mockito.Mock;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;

import java.util.Map;

import static org.mockito.Mockito.when;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;

@SpringBootTest
class AuthorizationServerTests {

    @Autowired
    private WebApplicationContext context;

    private MockMvc mockMvc;

    @Test
    void testTokenEndpoint() throws Exception {
        mockMvc = MockMvcBuilders.webAppContextSetup(context).build();

        // Test the token endpoint
        mockMvc.perform(post("/oauth2/token")
                        .header("Authorization", "test")
                        .contentType(MediaType.APPLICATION_FORM_URLENCODED)
                        .param("grant_type", "client_credentials")
                        .param("scope", "read")
                        .param("client_id", "test")
                        .param("client_secret", "test"))
                .andExpect(status().isOk())
                .andExpect(jsonPath("$.access_token").exists());
    }
}

错误日志

2024-12-30T00:11:41.836+02:00  INFO 8196 --- [test] [    Test worker] o.s.t.web.servlet.TestDispatcherServlet  : Completed initialization in 4 ms
2024-12-30T00:11:41.933+02:00 DEBUG 8196 --- [test] [    Test worker] o.s.t.web.servlet.TestDispatcherServlet  : POST "/oauth2/token", parameters={masked}
2024-12-30T00:11:41.956+02:00 DEBUG 8196 --- [test] [    Test worker] o.s.w.s.handler.SimpleUrlHandlerMapping  : Mapped to ResourceHttpRequestHandler [classpath [META-INF/resources/], classpath [resources/], classpath [static/], classpath [public/], ServletContext [/]]
2024-12-30T00:11:41.978+02:00 DEBUG 8196 --- [test] [    Test worker] o.s.w.s.r.ResourceHttpRequestHandler     : Resource not found
2024-12-30T00:11:41.987+02:00 DEBUG 8196 --- [test] [    Test worker] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.web.servlet.resource.NoResourceFoundException: No static resource oauth2/token.]
2024-12-30T00:11:41.988+02:00 DEBUG 8196 --- [test] [    Test worker] o.s.t.web.servlet.TestDispatcherServlet  : Completed 404 NOT_FOUND
原因分析
  1. MockMvc未加载Spring Security过滤器链:Spring Authorization Server的端点由Spring Security负责注册和管理,直接通过MockMvcBuilders.webAppContextSetup(context).build()初始化的MockMvc不会包含Spring Security的配置,导致端点未被正确映射,请求被默认路由到静态资源处理器。
  2. 无用的@Mock注解干扰上下文:测试类中使用了@Mock注解但未配合@MockBean使用,可能导致Spring上下文初始化不完整,影响Authorization Server配置的加载。
  3. Authorization Header格式错误:测试中设置的Authorization: test不符合OAuth2客户端凭证模式的Basic认证规范,Postman可能正确使用了Base64编码的凭证,而测试中的错误格式也可能导致请求异常。
解决方案
  1. 初始化MockMvc时应用Spring Security配置:导入SecurityMockMvcConfigurers.springSecurity(),在构建MockMvc时应用该配置,确保Spring Security的过滤器链被加载,端点能正确映射。
  2. 移除无用的@Mock注解:删除测试类中未使用的@Mock注解和相关静态导入,避免干扰Spring上下文。
  3. 修正Authorization Header格式:客户端凭证模式下,Authorization header需要使用Basic认证,格式为Basic {base64(client_id:client_secret)},比如test:test的Base64编码是dGVzdDp0ZXN0,所以header值应为Basic dGVzdDp0ZXN0。同时,客户端凭证模式下无需在请求参数中传递client_id和client_secret(已通过Header传递)。

修改后的测试代码

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.MediaType;
import org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;

import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

@SpringBootTest
class AuthorizationServerTests {

    @Autowired
    private WebApplicationContext context;

    private MockMvc mockMvc;

    @BeforeEach
    void setup() {
        // 应用Spring Security配置初始化MockMvc
        mockMvc = MockMvcBuilders.webAppContextSetup(context)
                .apply(SecurityMockMvcConfigurers.springSecurity())
                .build();
    }

    @Test
    void testTokenEndpoint() throws Exception {
        mockMvc.perform(post("/oauth2/token")
                        .header("Authorization", "Basic dGVzdDp0ZXN0")
                        .contentType(MediaType.APPLICATION_FORM_URLENCODED)
                        .param("grant_type", "client_credentials")
                        .param("scope", "read"))
                .andExpect(status().isOk())
                .andExpect(jsonPath("$.access_token").exists());
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 06:55:55