Matthew Kirkley
Matthew Kirkley

Reputation: 4208

Mockito in order verify with any matchers

I'm having some issues testing a servlet filter. The purpose of this servlet filter is to populate some http headers on response after the filterChain has been executed. So what I am trying to test is that setHeader calls on my mockHttpServletResponse don't happen until after mockFilterChain.doFilter is called.

I am using mockito:mockito-core:1.8.5

So, here is a sample code snippet

@Test
public void filterHeaderInjectionHappensLast() throws Exception {
    javax.servlet.Filter myFilter = new HeaderInjectionFilter();

    mockRequest = mock(javax.servlet.http.HttpServletRequest.class);
    mockResponse = mock(javax.servlet.http.HttpServletResponse.class);
    mockFilterChain = mock(javax.servlet.FilterChain.class);

    myFilter.doFilter(mockRequest, mockResponse, mockFilterChain);

    InOrder inOrder = inOrder(mockFilterChain, mockResponse);
    inOrder.verify(mockFilterChain).doFilter(mockRequest,mockResponse);
    inOrder.verify(mockResponse).setHeader(any(String.class),any(String.class));    
}

That test will fail do to the verify of setHeader passing any string arguments. If I change that setHeader verification call to accept specific arguments that are used in the code the test will pass successfully. Can you not use wildcard matchers when you are verifying order like this?

HeaderInjectionFilter dumbed down looks like this

public class HeaderInjectionFilter implements Filter {
    @Override
    public void destroy() {}

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {}

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException {
        filterChain.doFilter(request, response); //Always doFilter before we add header to response

        HttpServletResponse httpServletResponse = (HttpServletResponse) response;
        httpServletResponse.setHeader(CACHE_CONTROL, "no-cache");
        httpServletResponse.setHeader(PRAGMA, "no-cache");
    }
}

Upvotes: 1

Views: 7790

Answers (1)

Matthew Kirkley
Matthew Kirkley

Reputation: 4208

This test was failing using any(String.class) because in the Filter implementation provided, two subsequent calls to response.setHeader. inOrder.verify verifies that the interaction happens once in order. So technically the test could be altered to

@Test
public void filterHeaderInjectionHappensLast() throws Exception {
    javax.servlet.Filter myFilter = new HeaderInjectionFilter();

    mockRequest = mock(javax.servlet.http.HttpServletRequest.class);
    mockResponse = mock(javax.servlet.http.HttpServletResponse.class);
    mockFilterChain = mock(javax.servlet.FilterChain.class);

    myFilter.doFilter(mockRequest, mockResponse, mockFilterChain);

    InOrder inOrder = inOrder(mockFilterChain, mockResponse);
    inOrder.verify(mockFilterChain).doFilter(mockRequest,mockResponse);
    inOrder.verify(mockResponse, times(2)).setHeader(any(String.class),any(String.class));    
}

Or, the test should explicitely test the specific header was set which is the path I would go down since it is less obscure for someone reading the test.

Upvotes: 5

Related Questions