在 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) 编写单元测试的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Spring Boot 中为 Spring LDAP 身份验证设置覆盖 BindAuthenticator handleBindException

无法在 Spring Boot 中为 Hikari 设置 keepAlive Time 配置

Spring Boot参考教程Spring Boot配置Servlet,Filter,Listener,Interceptor

如何在 Spring Boot 中为 prometheus 制作自己的指标

spring boot filter -Autowired

如何在 Spring Boot 2 中为 Spring Batch 配置数据源以进行测试