javajerseyjersey-test-framework

Unit test for filter in jersey-spring


I have added one health link to my web service in web.xml as

<filter>
    <filter-name>healthChecker</filter-name>
    <filter-class>test.HealthChecker</filter-class>
</filter>

<filter-mapping>
    <filter-name>healthChecker</filter-name>
    <url-pattern>/health</url-pattern>
</filter-mapping>
<filter>
    <filter-name>basicAuthenticationFilter</filter-name>
    <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
    <async-supported>true</async-supported><!-- filter supports asynchronous processing -->
</filter>
<filter-mapping>
    <filter-name>basicAuthenticationFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

Now I want to unit test this health check

@Test
public void testHealthCheck() {
    ClientHttpRequestFactory originalRequestFactory = restTemplate.getRequestFactory();
    try {
        WebTarget target = target().path("/health");;

        final Response mockResponse = target.request().get();

        Assert.assertNotNull("Response must not be null", mockResponse.getEntity());
    } finally {
        restTemplate.setRequestFactory(originalRequestFactory);
    }
}

Code for health checker is

public class HealthChecker implements Filter {

    @Override
    public void destroy() {
        //do nothing

    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, 
        FilterChain chain) throws IOException, ServletException {
        response.setContentType("text/json");
        String json ="{\"status\":\"UP\"}";
        response.getWriter().append(json);

    }

    @Override
    public void init(FilterConfig filter) throws ServletException {
         // do nothing

    }

}

Now when I execute this unit test I am getting 404 error. If I see target then url in target is http://localhost:9998/health, which is right.

I used this url in chrome but couldnot get anything.

This is done in jersey test framework


Solution

  • You don't use the right approach, a servlet filter is not meant to be used for this purpose, it is used to perform filtering tasks and here as you break the filter chain (you don't call chain.doFilter(request, response)), you block the request such that you get a 404 error.

    As you obviously use Jersey, you should rather create a rest component and test it with the Jersey Test Framework.

    Your rest component that will return the status as a JSON object anytime the path /health is requested:

    @Path("/health")
    public class HealthChecker {
    
        @GET
        @Produces(MediaType.APPLICATION_JSON)
        public Response check() {
            return Response.status(Response.Status.OK)
                .entity("{\"status\":\"UP\"}")
                .build();
        }
    }
    

    Then we test that we actually get what we expect:

    public class HealthCheckerTest extends JerseyTest {
    
        @Override
        protected Application configure() {
            return new ResourceConfig(HealthChecker.class);
        }
    
        @Test
        public void testCreateGroup() {
            Response response = target("/health").request()
                .accept(MediaType.APPLICATION_JSON)
                .get();
            Assert.assertEquals("{\"status\":\"UP\"}", response.readEntity(String.class));
        }
    }