【问题标题】:can't inject Providers mock in JerseyTest无法在 JerseyTest 中注入 Providers mock
【发布时间】:2015-06-16 09:42:53
【问题描述】:

我从过滤器的上下文中获取Providers 以定义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);
    }
}

但在测试中,我无法使用带有HttpServletRequest 的抽象绑定器在此过滤器中注入模拟,它工作正常,但Providers 不是模拟。测试示例:

@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;
    }

为什么HttpServletRequest 在过滤器中是模拟的,而Providers 不是?

【问题讨论】:

  • 我的猜测是因为它是由框架处理的。通常HttpServletRequest 将由框架处理,但因为你不是running within a servlet container,所以它使用你的模拟,因为找不到正常的模拟。你可以测试这个理论(我没有这样做),通过点击链接并设置 servlet 环境,看看是否仍然使用模拟请求。
  • 至于你想要完成的事情,为什么不创建一个虚拟的ContextResolver 并注册那个。这与尝试模拟 Providers 并返回 that ContextResolver 几乎相同
  • 我已经有上下文解析器公共类 JerseyObjectMapperProvider 实现了 ContextResolver { bla bla }。但没有在示例中添加...我已经在资源 onfig 中注册了它,但它没有帮助
  • “没有帮助”是什么意思。你的意思是它没有被发现?
  • providers.getContextResolver(ObjectMapper.class, MediaType.APPLICATION_JSON_TYPE) - 返回 null。

标签: java mocking jersey integration-testing inject


【解决方案1】:

提供者不应该被嘲笑。它由框架处理。您想要添加的任何提供者,只需注册ResourceConfig。我不知道您在尝试此操作时在意做错了什么,但下面是一个完整的工作示例,其中ContextResolver 被发现就好了。

如果您仍然无法弄清楚,请像我一样提供一个完整的工作单类示例(没有任何模拟或 Spring 的东西)。

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();
    }
}

【讨论】:

  • 谢谢,我真的相信,这个模板工作得很好......但在我的情况下(我这样做) - 不是,(可能是因为 Spring 的东西),我会尝试删除这个弹簧和嘲笑。但我认为这在我的情况下是不可能的。如果有帮助,我会更新这个问题的状态,或者显示我所有的代码示例)
  • 永远不知道)这应该在应用程序中,但现在不需要)
猜你喜欢
  • 2017-08-06
  • 2010-12-05
  • 2014-12-06
  • 1970-01-01
  • 1970-01-01
  • 2013-08-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多