【问题标题】:MockMvc throws internal exception instead of returning response with 4xx status codeMockMvc 抛出内部异常而不是返回带有 4xx 状态码的响应
【发布时间】:2021-01-27 18:58:53
【问题描述】:

我正在尝试使用 MockMvc 编写 JwtTokenVerifier 测试

当我尝试使用无效的 Auth 标头请求某些 API 时:它不是返回带有 4xx 状态代码的响应,而是引发内部异常(在我的情况下为 AuthException)。 我应该在测试中期待这个异常吗 或者我需要做些什么才能得到回应?

(值“”和“123”测试成功,但“承载 qewqweqweqwe”失败并出现 AuthException(io.jsonwebtoken.MalformedJwtException:JWT 字符串必须恰好包含 2 个句点字符。找到:0))

测试:

@ParameterizedTest
    @ValueSource(strings = {"", "123", "Bearer qewqweqweqwe"})
    public void throwsClientErrorOnRequestWithInvalidAuthHeader(String headerValue) throws Exception {
        String requestBody = asJsonString(new CustomPageRequest());

        mockMvc.perform(
                MockMvcRequestBuilders.post("/users/paged")
                        .header(jwtConfig.getAuthorizationHeader(), headerValue)
                        .contentType(MediaType.APPLICATION_JSON)
                        .content(requestBody))
                .andExpect(status().is4xxClientError());
    }

JwtTokenVerifier 过滤器:

public class JwtTokenVerifier extends OncePerRequestFilter {

    //DI

    @Override
    protected void doFilterInternal(HttpServletRequest request,
                                    HttpServletResponse response,
                                    FilterChain filterChain) throws ServletException, IOException {
        String authHeader = request.getHeader(jwtConfig.getAuthorizationHeader());
        if (StringUtils.isEmpty(authHeader) || !authHeader.startsWith(jwtConfig.getTokenPrefix())) {
            logger.warn("Invalid Authorization header - '" + authHeader + "'");
            filterChain.doFilter(request, response);
            return;
        }
        try {
            Claims body = getTokenBodyFromAuthHeader(authHeader);

            String username = body.getSubject();

            AuthUser userDetails = userDetailsService.loadUserByUsername(username);
            CustomTokenBasedAuthentication authentication = new CustomTokenBasedAuthentication(userDetails);
            SecurityContextHolder.getContext().setAuthentication(authentication);
            userContext.setCurrentPrincipal(authentication);
        } catch (JwtException e) {
            logger.error("During authentication (token verification) exception occurred", e);
            throw new AuthException("auth error");
        }
        filterChain.doFilter(request, response);
    }

    ...
}

ApiExceptionHandler:

@ControllerAdvice(basePackages = {"bac9h.demoapp"})
public class ApiExceptionsHandler {

    ...

    @ResponseStatus(HttpStatus.UNAUTHORIZED)
    @ExceptionHandler(AuthException.class)
    @ResponseBody
    public String onAuthException(AuthException e) {
        return "401 error: " + e.getMessage();
    }
}

【问题讨论】:

    标签: java spring-boot testing mockmvc


    【解决方案1】:

    看起来一切都已连接并正常工作,但是您的 JWT 解析器识别出您提供的 Bearer 令牌甚至不是 JWT 的有效格式,因此它会引发异常。

    我建议以正确的格式创建 JWT,BUT 在您的应用程序上下文中没有意义,以测试您尝试验证的行为。试试jwt.io。

    【讨论】:

      【解决方案2】:

      我意识到我的 apiExceptionHandler 不适用于过滤器

      Make simple servlet filter work with @ControllerAdvice:

      正如 java servlet 规范所指定的,过滤器总是在调用 Servlet 之前执行。现在 @ControllerAdvice 仅对在 DispatcherServlet 内执行的控制器有用。因此,使用过滤器并期望 @ControllerAdvice 或在本例中为 @ExceptionHandler 被调用是不会发生的。

      为了得到适当的响应,我需要手动提供异常处理程序

      Testing Spring MVC @ExceptionHandler method with Spring MVC Test

      @Before
      public void setup() {
          this.mockMvc = MockMvcBuilders.standaloneSetup(statusController)
               .setControllerAdvice(new ExceptionController())
              .build();
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-01-08
        • 2017-10-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-01-03
        • 2015-07-12
        相关资源
        最近更新 更多