在 Spring boot 中为 Filter (OncePerRequestFilter) 编写单元测试

Posted

技术标签:

【中文标题】在 Spring boot 中为 Filter (OncePerRequestFilter) 编写单元测试【英文标题】:Writing unit test for Filter (OncePerRequestFilter) in Spring boot 【发布时间】:2019-11-19 02:41:37 【问题描述】:

我有扩展 OncePerRequestFilter 的过滤器类。此过滤器用于捕获审计数据,然后传递给异步方法以持久保存在 db 中。 我需要为整个场景编写测试用例。如何做到这一点?我在 Junit 方面没有任何出色的专业知识。

public class AuditFilter extends OncePerRequestFilter 

  private static final Logger LOGGER = LoggerFactory.getLogger(AuditFilter.class);
  private AuditLogManager auditLogManager;
  private String auditMode;
  private List<String> urlPatterns;

  /**
   * @param auditLogManager - processes the audit logs.
   * @param auditMode - modes of auditing (OFF,BASIC,DETAILED).
   * @param urlPatterns - the URL patterns for which auditing to be done.
   */
  public AuditFilter(final AuditLogManager auditLogManager, final String auditMode,
      final List<String> urlPatterns) 
    this.auditLogManager = auditLogManager;
    this.auditMode = auditMode;
    this.urlPatterns = urlPatterns;
  

  @Override()
  protected void doFilterInternal(final HttpServletRequest request,
      final HttpServletResponse response, final FilterChain filterChain)
      throws ServletException, IOException 
    //capture audit data from request
      try 
        filterChain.doFilter(wrappedRequest, wrappedResponse);
       finally 
        //capture audit data from response
        // Executing asynchronous call. auditLogManager uses @Async annotation. Need i=integration test for auditLogManager code also
        auditLogManager.log(auditInfo, auditMode);
          
   

我需要在 maven 构建期间对 AuditFilter 和 AuditLogManager(具有异步方法的类)执行的每个操作进行单元测试。

【问题讨论】:

您的问题令人困惑。你想要单元测试还是集成测试?两者完全不同。单元测试是针对原始 Java 源代码执行的(在部署之前)。针对正在运行的服务器执行集成测试(部署后)。对于单元测试,您需要某种模拟库(例如 Mockito)来模拟与真实运行的服务器上相同的条件(因此这很可疑)。对于集成测试,您需要一个复杂的集成测试框架(例如 Arquillian+Selenium),但您没有指定当前使用的是哪一个。 抱歉没有正确提及。我只需要一个单元测试。这些测试用例应该在我构建项目时执行。就是这样。 在构建过程中也会执行集成测试。 我想我需要做如下。首先,我需要测试我的 OncePerRequestFilter。而从过滤器中调用的异步代码,我需要单独测试。是吗? 【参考方案1】:

这可能是迟到的回应。但是可以使用另一种方法。

对于当前的 spring 2.5.5,一种选择是使用 RestTemplate 方法

// use below annotation at class level
// the WebEnvironment with Random_port, this is required for test case
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)

@Test
    void postTest() 
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        String bodyContent = "\"appAPI\":\"<SOME-API-CODE-or-USER-NAME>\"";

        HttpEntity<String> requestEntity = new HttpEntity<>(bodyContent, headers);
        //END POINT exposed in myapp, which will be used to provide the token.
        String token = restTemplate
                .postForObject("/myapp/authenticate",requestEntity, String.class);

        ObjectMapper mapper = new ObjectMapper();
        JsonNode root;
        try 
            root = mapper.readTree(token);
            JsonNode tokenVal = root.path("jwtToken");
            System.out.println("TKN: "+tokenVal.asText());
            Assert.isTrue(tokenVal.asText()!=null, "Token received successfully");
         catch (JsonProcessingException e) 
            Assert.isTrue(false,"Exception occurred: "+e.getMessage());
        

    

就我而言,我有一个用于 jwt 响应的 Java POJO,因此来自 POST 端点的响应是一个 POJO,因此使用 ObjectMapper 进行解析和验证。

【讨论】:

以上是关于在 Spring boot 中为 Filter (OncePerRequestFilter) 编写单元测试的主要内容,如果未能解决你的问题,请参考以下文章