3

I'm getting Providers from context in my filter to get defined ObjectMapper

 public class Filter implements ContainerRequestFilter, ContainerResponseFilter {

    @Context
    private Providers providers;
    @Context
    private HttpServletRequest request;

    private ObjectMapper getObjectMapper() {
        ContextResolver<ObjectMapper> contextResolver = providers.getContextResolver(ObjectMapper.class, MediaType.APPLICATION_JSON_TYPE);
        if (contextResolver == null) {
            return new ObjectMapper();
        }
        return contextResolver.getContext(null);
    }
}

but in test I can't inject mock in this filter using abstract binder with HttpServletRequest it works fine but Providers isn't mock. Example of test:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration({ "..." })
@PrepareForTest({ ... })
public class Test extends JerseyTest {

    @Rule
    public PowerMockRule rule = new PowerMockRule();
    private HttpServletRequest request;
    private Providers providers;

    @Override
    protected Application configure() {
        ResourceConfig config = new ResourceConfig(TestResource.class, Filter.class);
        providers = mock(Providers.class);
        request = mock(HttpServletRequest.class);
        config.register(new AbstractBinder() {
            @Override
            protected void configure() {
                bind(providers).to(Providers.class);
            }
        });
        config.register(new AbstractBinder() {
            @Override
            protected void configure() {
                bind(request).to(HttpServletRequest.class);
            }
        });

        return config;
    }

Why HttpServletRequest is mock in filter but Providers is not?

Paul Samsotha
  • 205,037
  • 37
  • 486
  • 720
Capril Aprilovich
  • 425
  • 1
  • 6
  • 17
  • My guess is because it's handled by the framework. Normally `HttpServletRequest` would be handled by the framework, but because you are not [running within a servlet container](http://stackoverflow.com/a/28437888/2587435), it uses your mock, as the normal one can't be found. You can test this theory (I have not done so), by following the link and setting up the servlet environment, to see if the mock request is still used. – Paul Samsotha Jun 16 '15 at 10:23
  • As far as what you trying to accomplish, why not just create a dummy `ContextResolver` and register _that_. It''s pretty much the same thing as trying to mock the `Providers` and returning _that_ `ContextResolver` – Paul Samsotha Jun 16 '15 at 10:27
  • I have already context resolver public class JerseyObjectMapperProvider implements ContextResolver { bla bla }. but didn't added here in example... I've registred it in resoutce onfig but it doesn't help – Capril Aprilovich Jun 16 '15 at 11:50
  • What do you mean "didn't help". Do you mean it's not being discovered? – Paul Samsotha Jun 16 '15 at 11:59
  • providers.getContextResolver(ObjectMapper.class, MediaType.APPLICATION_JSON_TYPE) - return null. – Capril Aprilovich Jun 16 '15 at 12:21

1 Answers1

1

Providers shouldn't have to be mocked. It is handled by the framework. Any providers you want added, just register with the ResourceConfig. I don't know what you care doing wrong in your attempt at this, but below is a complete working example where the ContextResolver is discovered just fine.

If you still can't figure it out, please provide a full working single class example (without any mock or Spring stuff) like I have done.

import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.IOException;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.container.ContainerRequestFilter;
import javax.ws.rs.core.Application;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.ext.ContextResolver;
import javax.ws.rs.ext.Provider;
import javax.ws.rs.ext.Providers;
import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.jersey.test.JerseyTest;
import org.junit.Assert;
import org.junit.Test;

public class ContextResolverTest extends JerseyTest {

    @Provider
    @Produces(MediaType.APPLICATION_JSON)
    @Consumes(MediaType.APPLICATION_JSON)
    public static class OMContextResolver implements ContextResolver<ObjectMapper> {

        private final ObjectMapper mapper = new ObjectMapper();

        @Override
        public ObjectMapper getContext(Class<?> type) {
            return mapper;
        }
    }

    @Provider
    public static class Filter implements ContainerRequestFilter  {

        @Context
        private Providers providers;

        @Override
        public void filter(ContainerRequestContext requestContext) throws IOException { 
            ContextResolver<ObjectMapper> contextResolver 
                    = providers.getContextResolver(ObjectMapper.class, 
                            MediaType.APPLICATION_JSON_TYPE);
            if (contextResolver == null) {
                requestContext.abortWith(
                            Response.serverError().entity("no resolver").build());
            } else {
                ObjectMapper mapper = contextResolver.getContext(null);
                if (mapper == null) {
                    requestContext.abortWith(
                            Response.serverError().entity("no mapper").build());
                    return;
                }
                requestContext.abortWith(
                            Response.ok("resolver found").build());
            }
        }
    }

    @Path("test")
    public static class TestResource {
        @GET
        public String dummyGet() {
            return "Boo";
        }
    }

    @Override
    public Application configure() {
        ResourceConfig config = new ResourceConfig();
        config.register(TestResource.class);
        config.register(OMContextResolver.class);
        config.register(Filter.class);
        return config;
    }

    @Test
    public void contextResolverIsOk() {
        Response response = target("test").request().get();
        Assert.assertEquals(200, response.getStatus());
        Assert.assertEquals("resolver found", response.readEntity(String.class));
        response.close();
    }
}
Paul Samsotha
  • 205,037
  • 37
  • 486
  • 720
  • thanks, I really believe, that this template works fine... but in my case (I do it in this way) - is not, (may be because of Spring's stuff), I'll try to remove this spring and mocks. But I think this is impossible in my case. I'll update status of this question if it help, either show all my code example) – Capril Aprilovich Jun 16 '15 at 13:56
  • It never be known) this should be in application but now not needed) – Capril Aprilovich Jun 18 '15 at 13:09