使用jersey-spring3从JerseyTest容器中检索托管bean

此问题是从上一个问题指定自定义应用程序上下文的后续问题。

我们正在使用泽西弹簧3将泽西1.x的一些数据服务从泽西1.x迁移到泽西2.x.

我们有几个inheritance自JerseyTest的测试类。 其中一些类使用未在web.xml文件中指定的自定义applicationContext.xml文件。

出于对象模拟的目的,我们将在Jersey资源中模拟一些组件。

在Jersey 1.x中,我们可以通过模拟应用程序上下文文件中的对象

   

并检索这些模拟的实例如下

 ClassToMock obj = (ClassToMock)ContextLoader .getCurrentWebApplicationContext() .getAutowireCapableBeanFactory() .getBean("mockBean"); 

如何使用Jersey 2.x使用jersey-spring3实现同样的目标?

我已经梳理了API文档 , 用户指南和一些来源,但无法找到答案。

谢谢。

编辑:

我们将在JAX-RS资源中使用模拟bean。 我们的服务接口已经@Autowired到我们的资源中。

例如

 @Path(ProductResource.RESOURCE_PATH) @Component @Scope("prototype") public class ProductResource extends GenericResource { /* * Members */ public static final String RESOURCE_PATH = "product/"; @Autowired protected ProductService productService; ... 

我们想要模拟并设定对这些服务的期望。

例如

    

注意:我不是Spring专家,我认为这是一种解决方案,而不是推荐的方法。 希望有人会提出更好的解决方案。

您无法通过调用ContextLoader#getCurrentWebApplicationContext()来获取ApplicationContext实例,因为在使用Jersey Test Framework( JerseyTest )进行单元/ e2e测试时,默认情况下将Jersey 2.x运行时初始化在Servlet容器之外。

在这种情况下,您需要通过在测试包中实现ApplicationContextAware接口来使用一些解决方法来获取ApplicationContext

 public class ApplicationContextUtils implements ApplicationContextAware { private static ApplicationContext applicationContext; public static ApplicationContext getApplicationContext() { return applicationContext; } @Override public void setApplicationContext(final ApplicationContext applicationContext) throws BeansException { ApplicationContextUtils.applicationContext = applicationContext; } } 

有了这个类,不要忘记在应用程序上下文描述符中提及它:

 ...  ... 

你可以在测试中使用它:

 public class JerseySpringResourceTest extends JerseyTest { // ... Configure ... @Before public void mockUp() throws Exception { // ApplicationContext is ready in your @Before methods ... assertThat(ApplicationContextUtils.getApplicationContext(), notNullValue()); } @Test public void testJerseyResource() { // ... as well as in your test methods. assertThat(ApplicationContextUtils.getApplicationContext(), notNullValue()); } } 

注意:如果要将应用程序部署到Servlet容器并针对它运行( JerseyTest )测试,请参阅“用户指南”(特别是外部容器部分)中的Jersey Test Framework一章。

如果您对此没有任何异议,可以将测试类注入Jersey上下文。

例如:

 @Override protected Application configure() { final TestJerseyApplication application = new TestJerseyApplication(); final Map properties = new HashMap<>(); properties.put("contextConfigLocation", "classpath:test-spring-context.xml"); application.setProperties(properties); application.register(this); return application; } 

之后@Autowired注释将适合您。

对于Jersey 2.X用户来说,这对我有用:

  public class AccountResourceTest extends JerseyTest { private ApplicationContext context; private BeanA beanA; private BeanB beanB; public AccountResourceTest() throws TestContainerException { super(); beanA = context.getBean(BeanA.class); beanB = context.getBean(BeanB.class); } @Override protected Application configure() { context = new AnnotationConfigApplicationContext(SpringConfiguration.class); final ResourceConfig config = new JerseyConfiguration().property("contextConfig", context); return config; } @Override protected void configureClient(final ClientConfig config) { config.register(JacksonJsonProvider.class); } ... } 

这允许我使用JavaConfig进行Jersey测试,并在上下文中访问bean。 这是我得到这个想法的链接: http : //geowarin.github.io/spring-boot/jersey/2014/01/31/a-simple-spring-boot-and-jersey-application.html

对于Jersey版本2.4.x, JerseyConfiguration类不再存在,并且已被ResourceConfig取代,而ResourceConfig不理解contextConfig属性。 这是我的解决方案:

 package ch.vd.test; import java.net.URI; import javax.ws.rs.core.Application; import org.glassfish.hk2.api.ServiceLocator; import org.glassfish.jersey.server.ApplicationHandler; import org.glassfish.jersey.server.ResourceConfig; import org.glassfish.jersey.test.JerseyTest; import org.glassfish.jersey.test.grizzly.GrizzlyTestContainerFactory; import org.glassfish.jersey.test.spi.TestContainer; import org.glassfish.jersey.test.spi.TestContainerException; import org.glassfish.jersey.test.spi.TestContainerFactory; import org.junit.Test; import org.springframework.context.ApplicationContext; public class ExampleTest extends JerseyTest { private ServiceLocator serviceLocator; @Override public void setUp() throws Exception { super.setUp(); final ApplicationContext context = serviceLocator.getService(ApplicationContext.class, "SpringContext"); final Object bean = context.getBean("someBean"); } @Override protected Application configure() { final ResourceConfig config = new ResourceConfig(RestResources.class); config.property("contextConfigLocation", "classpath:example-context.xml"); return config; } @Override protected TestContainerFactory getTestContainerFactory() throws TestContainerException { return new GrizzlyTestContainerFactory() { @Override public TestContainer create(URI uri, ApplicationHandler appHandler) throws IllegalArgumentException { serviceLocator = appHandler.getServiceLocator(); return super.create(uri, appHandler); } }; } @Test public void testStuff() throws Exception { ... } }