Java 使用jersey-spring3从jersey测试容器中检索托管bean

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.

这个问题是上一个问题的后续问题

我们正在将一些数据服务从使用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.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;
}