首页 > 解决方案 > 如何编写集成测试来检查 MDC 上下文中的内容?

问题描述

这是我用来向标题添加过滤器并添加 UUID 的代码

@Slf4j
public class ReqTxIdFilterImpl implements Filter {

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
            throws IOException, ServletException {

        HttpServletRequest request = (HttpServletRequest) servletRequest;
        List<String> headerNames = Collections.list(request.getHeaderNames());
        String requestTxId = "";
        if(!headerNames.isEmpty()){
            requestTxId = request.getHeader(
                    headerNames.stream()//
                            .filter(header -> header.contains("txId"))
                            .findAny()
                            .orElse("")//
                    );
        }
        if (StringUtils.isEmpty(requestTxId)) {
            requestTxId = UUID.randomUUID().toString();
        }
        MDC.put("txId", requestTxId);
        filterChain.doFilter(servletRequest, servletResponse);
        MDC.clear();
    }
}

我使用 spring boot 和 MockMvc 来测试 API

@Autowired
    private MockMvc mockMvc;

    @Test
    public void test_generatePolicyNumber() throws Exception {
        MvcResult mvcResult = this.mockMvc.perform(post("/test"))
                .header("txId", "test-id")
                .andDo(print()).andExpect(status().isOk())
                .andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8_VALUE))
                .andReturn();
        Assert.assertTrue(mvcResult.getResponse().getContentAsString().contains("test"));
    }

我还想检查 MDC 上下文并检查此test-id是否在 MDC 上下文映射中设置为 txId 并验证它。可能吗 ?

标签: javaspring-bootlogbackmdc

解决方案


你想做的事情有点复杂,但一个可能的解决方案是使用参数捕获器。

例如:

public class ReqTxIdFilterImpl implements Filter {

    @Override
    public void doFilter(...) {
       // rest of code
       addIdToMdc(requestTxId);
       filterChain.doFilter(servletRequest, servletResponse);
       MDC.clear();
    }

    protected void addIdToMdc(String requestTxId) { 
       MDC.put("txId", requestTxId);  
    }
}

在测试类中:

    @Test
    public void test_generatePolicyNumber() throws Exception {
      ...
      ArgumentCaptor<String> captor = ArgumentCaptor.forClass(String.class);
      Mockito.verify(filter).addIdToMdc(captor.capture());

      //get the String object added to MDC using ArgumentCaptor
      String actual = captor.getValue();
      Assert.assertThat(actual).isEqualTo(expectedId);
   }

请注意,您需要在您的 TestClass 中注入过滤器,我不确定它在您的情况下是否可行。

一种解决方案是将用于将该 Id 组合到另一个组件中的逻辑提取并测试该类或为其调用 ResultCaptor。:https://stackoverflow.com/a/25694142/8794926


推荐阅读