Java 使用jersey-spring3从jersey测试容器中检索托管bean
这个问题是上一个问题的后续问题 我们正在将一些数据服务从使用Jersey-spring的Jersey 1.x迁移到使用Jersey-spring3的Jersey 2.x 我们有几个从JerseyTest继承的测试类。其中一些类使用web.xml文件中未指定的自定义applicationContext.xml文件 出于对象模拟的目的,我们将模拟Jersey资源中的一些组件 在Jersey 1.x中,我们可以通过Java 使用jersey-spring3从jersey测试容器中检索托管bean,java,spring,unit-testing,jersey-2.0,Java,Spring,Unit Testing,Jersey 2.0,这个问题是上一个问题的后续问题 我们正在将一些数据服务从使用Jersey-spring的Jersey 1.x迁移到使用Jersey-spring3的Jersey 2.x 我们有几个从JerseyTest继承的测试类。其中一些类使用web.xml文件中未指定的自定义applicationContext.xml文件 出于对象模拟的目的,我们将模拟Jersey资源中的一些组件 在Jersey 1.x中,我们可以通过 <bean id="mockBean" class="org.easymock.
<bean id="mockBean" class="org.easymock.EasyMock"
factory-method="createStrictMock" autowire="byName">
<constructor-arg index="0" value="com.xxx.xxx.ClassToMock" />
</bean>
Jersey 2.x如何使用Jersey-spring3实现同样的效果
我已经仔细地梳理了一些问题,但找不到答案
多谢各位
编辑:
我们将在JAX-RS资源中使用模拟bean。我们有@自动连接到资源中的服务接口
e、 g
@Path(ProductResource.RESOURCE\u路径)
@组成部分
@范围(“原型”)
公共类产品资源
扩展通用资源{
/*
*成员
*/
公共静态最终字符串资源_PATH=“product/”;
@自动连线
受保护产品服务产品服务;
...
我们希望模拟这些服务,并设定对这些服务的期望
e、 g
< >代码> <强>注:< /强>我不是Spring专家,我认为这是一个比推荐的方法更有效的工作。希望有人能想出一个更好的解决方案。
通过调用ContextLoader#getCurrentWebApplicationContext()
无法获得ApplicationContext
实例,因为当使用Jersey测试框架(Jersey Test
)进行单元/e2e测试时,Jersey 2.x运行时默认在Servlet容器外部初始化
在这种情况下,您需要通过在测试包中实现接口来使用一些变通方法来获得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;
}
}
拥有此类后,不要忘记在应用程序上下文描述符中提及它:
...
<bean class="org.glassfish.jersey.examples.helloworld.spring.ApplicationContextUtils" />
...
注意:如果您想将应用程序部署到Servlet容器并对其运行(JerseyTest
)测试,请参阅《用户指南》中的一章(特别是一节)。对于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);
}
...
}
这允许我在Jersey测试中使用JavaConfig,并在上下文中访问bean。下面是我的想法的链接:对于Jersey版本2.4.x,类Jersey配置
不再存在,已被不理解contextConfig属性的ResourceConfig
取代。以下是我的解决方案:
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 {
...
}
}
如果没有任何异议,可以将测试类注入Jersey上下文
例如:
@Override
protected Application configure() {
final TestJerseyApplication application = new TestJerseyApplication();
final Map<String, Object> properties = new HashMap<>();
properties.put("contextConfigLocation", "classpath:test-spring-context.xml");
application.setProperties(properties);
application.register(this);
return application;
}
@覆盖
受保护的应用程序配置(){
最终TestJersey应用程序=新的TestJersey应用程序();
最终映射属性=新HashMap();
put(“contextConfigLocation”,“classpath:testspringcontext.xml”);
应用程序。设置属性(属性);
申请登记(本);
退货申请;
}
之后,@Autowired
注释将对您起作用。您可以用一个例子来说明这一点吗?(如何/何时/何地使用模拟bean?它是否在JAX-RS资源中?)您是否需要确切的WebApplicationContext
或任何ApplicationContext
就足够了?无论是WebApplicationContext
还是ApplicationContext
都可以。这都会给我们一个指向注入JAX-RS资源的bean的指针。感谢您的反馈。我会尽快对它进行测试我可以。只有一个问题。在setApplicationContext
中,不应该this.applicationContext=applicationContext;
而是ApplicationContextUtils.applicationContext=applicationContext;
因为applicationContext是一个静态字段。也可以在ApplicationContextUtils上使用'@Component'注释(确保它位于组件扫描的包中),从而不再需要显式声明bean。啊,我们可以通过“contextConfigLocation”而不是默认的“applicationContext.xml”名称告诉Jersey要查找哪个自定义Spring上下文文件。
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());
}
}
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);
}
...
}
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 {
...
}
}
@Override
protected Application configure() {
final TestJerseyApplication application = new TestJerseyApplication();
final Map<String, Object> properties = new HashMap<>();
properties.put("contextConfigLocation", "classpath:test-spring-context.xml");
application.setProperties(properties);
application.register(this);
return application;
}