我如何对这个 doFilter() 方法进行单元测试?

How do I unit test this doFilter() method?

有人可以帮助我编写单元测试代码吗?我总是得到 Null Pointer Exception,因为这段代码在 MyFilter returns null

Request jettyRequest = Request.getBaseRequest(servletRequest);

代码

 public class MyFilter implements Filter {


  @Override
  public void init(final FilterConfig filterConfig) {
    LOG.info("My filter");
  }

  @Override
  public void doFilter(
      ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
      throws IOException, ServletException {
    final String startTime = String.valueOf(System.currentTimeMillis());

    Request jettyRequest = Request.getBaseRequest(servletRequest);
    String requestId = jettyRequest.getHeader(HttpHeaderUtils.APP_ID_HEADER);

    filterChain.doFilter(servletRequest, httpResponse);
  }

单元测试

public class MyFilterTest {

  private MockHttpServletRequest httpRequest;
  private MyFilter myFilter = new MediaRequestFilter(8888);

  @Before
  public void init() {
    httpRequest = new MockHttpServletRequest();
    httpRequest.addHeader(HttpHeaderUtils.REQUEST_ID_HEADER, 1);

    mediaRequestFilter.init(null);
  }

  @Test
  public void doFilterTest() throws IOException, ServletException {
    myFilter.doFilter(httpRequest, new MockHttpServletResponse(), new MockFilterChain());
    Assert.assertTrue(Long.valueOf(httpRequest.getHeader(HttpHeaderUtils.REQUEST_ID_HEADER)) > 0);
  }
}

我们可以使用间谍来帮助处理您的案件。您不能使用 Mockito 模拟静态方法。你可以使用 PowerMockito 来做,但我会告诉你一个不同的方法。

所以,我稍微改变了你的 class。假设它仍然是您的代码。我刚刚添加了一个 Request class 因为我真的不想搜索那个特定的 class。

@Slf4j
public class MyFilter implements Filter {

    @Override
    public void init(final FilterConfig filterConfig) {
        log.info("My filter");
    }

    @Override
    public void doFilter(ServletRequest servletRequest,
                         ServletResponse servletResponse,
                         FilterChain filterChain) throws IOException, ServletException {
        Request jettyRequest = getBaseRequest(servletRequest);
        String requestId = jettyRequest.getHeader("Some header");

        log.info("Request id : {}", requestId);

        filterChain.doFilter(servletRequest, servletResponse);
    }

    Request getBaseRequest(ServletRequest servletRequest) {
        return Request.getBaseRequest(servletRequest);
    }

}

请注意,我将该静态方法调用转换为实例方法调用,并使该方法成为 package-private。我这样做是为了能够在我们的测试中访问它。

这是测试

@ExtendWith(MockitoExtension.class)
class MyFilterTest {

    @Test
    @SneakyThrows
    void testDoFilter() {
        final MyFilter myFilter = spy(new MyFilter());

        final ServletRequest req = mock(ServletRequest.class);
        final ServletResponse res = mock(ServletResponse.class);
        final FilterChain chain = mock(FilterChain.class);

        doReturn(new Request()).when(myFilter).getBaseRequest(req);

        myFilter.doFilter(req, res, chain);

        verify(chain).doFilter(req, res);
        verify(myFilter).getBaseRequest(req);
    }

}

我正在使用间谍模拟对象的特定部分,即静态方法调用。而已。您可以模拟 Request 对象并对其进行各种验证。