1

我有一个简单的资源,例如:

@Path("/")
public class RootResource {
    @Context WebConfig wc;

    @PostConstruct 
    public void init() {
        assertNotNull(wc);
    }

    @GET
    public void String method() {
        return "Hello\n";
    }
}

我正在尝试将其与 JerseyTest(2.x,而不是 1.x)和 GrizzlyTestContainerFactory 一起使用。

我无法确定在配置方面需要做什么才能注入 WebConfig 对象。

4

2 回答 2

5

我通过创建 GrizzlyTestContainerFactory 的子类并显式加载 Jersey servlet 解决了这个问题。这会触发 WebConfig 对象的注入。代码如下所示:

public class ExtendedGrizzlyTestContainerFactory implements TestContainerFactory {

    private static class GrizzlyTestContainer implements TestContainer {

        private final URI uri;
        private final ApplicationHandler appHandler;
        private HttpServer server;
        private static final Logger LOGGER = Logger.getLogger(GrizzlyTestContainer.class.getName());

        private GrizzlyTestContainer(URI uri, ApplicationHandler appHandler) {
            this.appHandler = appHandler;
            this.uri = uri;
        }

        @Override
        public ClientConfig getClientConfig() {
            return null;
        }

        @Override
        public URI getBaseUri() {
            return uri;
        }

        @Override
        public void start() {
            if (LOGGER.isLoggable(Level.INFO)) {
                LOGGER.log(Level.INFO, "Starting GrizzlyTestContainer...");
            }

            try {
                this.server = GrizzlyHttpServerFactory.createHttpServer(uri, appHandler);

                // Initialize and register Jersey Servlet
                WebappContext context = new WebappContext("WebappContext", "");
                ServletRegistration registration = context.addServlet("ServletContainer", ServletContainer.class);
                registration.setInitParameter("javax.ws.rs.Application", 
                        appHandler.getConfiguration().getApplication().getClass().getName());
                // Add an init parameter - this could be loaded from a parameter in the constructor
                registration.setInitParameter("myparam", "myvalue");
                registration.addMapping("/*");
                context.deploy(server);

            } catch (ProcessingException e) {
                 throw new TestContainerException(e);
            }
        }

        @Override
        public void stop() {
             if (LOGGER.isLoggable(Level.INFO)) {
                 LOGGER.log(Level.INFO, "Stopping GrizzlyTestContainer...");
            }
            this.server.stop();
        }
    }

    @Override
    public TestContainer create(URI baseUri, ApplicationHandler application) throws IllegalArgumentException {
         return new GrizzlyTestContainer(baseUri, application);
    }

请注意,Jersey Servlet 配置是从作为参数传入的 ApplicationHandler 加载的,该参数使用内部 Application 对象的类名(ResourceConfig 是 Application 的子类)。因此,您还需要创建 ResourceConfig 的子类才能使这种方法起作用。代码非常简单:

package com.example;

import org.glassfish.jersey.server.ResourceConfig;

public class MyResourceConfig extends ResourceConfig {

    public MyResourceConfig() {
        super(MyResource.class);
    }

} 

这假定您正在测试的资源是 MyResource。您还需要在测试中重写几个方法,如下所示:

public class MyResourceTest extends JerseyTest {

    public MyResourceTest() throws TestContainerException {

    }

    @Override
    protected Application configure() {
        return new MyResourceConfig();
    }

    @Override
    protected TestContainerFactory getTestContainerFactory() throws TestContainerException {
        return new ExtendedGrizzlyTestContainerFactory();
    }

    @Test
    public void testCreateSimpleBean() {
        final String beanList = target("test").request().get(String.class);
        Assert.assertNotNull(beanList);
    }

}

最后,为了完整起见,这里是 MyResource 的代码:

@Path("test")
public class MyResource {

    @Context WebConfig wc;

    @PostConstruct 
    public void init() {
        System.out.println("WebConfig: " + wc);
        String url = wc.getInitParameter("myparam");
        System.out.println("myparam = "+url);
    }

    @GET
    @Produces(MediaType.APPLICATION_JSON)
    public Collection<TestBean> createSimpleBean() {
        Collection<TestBean> res = new ArrayList<TestBean>();
        res.add(new TestBean("a", 1, 1L));
        res.add(new TestBean("b", 2, 2L));
        return res;
    }

    @POST
    @Produces(MediaType.APPLICATION_JSON)
    @Consumes(MediaType.APPLICATION_JSON)
    public TestBean roundTrip(TestBean s) {
        return s;
    }
}

运行测试的输出显示 WebConfig 已加载并且 init 参数现在可用:

WebConfig: org.glassfish.jersey.servlet.WebServletConfig@107d0f44
myparam = myvalue
于 2013-07-16T06:44:31.107 回答
0

@ametke 的解决方案运行良好,但没有使用我的 ExceptionMapper 类。为了解决这个问题,我将start()方法简化为:

@Override
public void start() {
  try {
    initParams.put("jersey.config.server.provider.packages", "my.resources;my.config");
    this.server = GrizzlyWebContainerFactory.create(uri, initParams);
  } catch (ProcessingException | IOException e) {
    throw new TestContainerException(e);
  }
}

这是基于在处理 HttpServletResponse 时运行 JerseyTest 的问题

于 2013-11-09T10:08:05.387 回答