简体   繁体   English

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

[英]Retrieve a managed bean from a JerseyTest container with jersey-spring3

This question is a follow on from a previous question Specify Custom Application Context . 此问题是从上一个问题指定自定义应用程序上下文的后续问题。

We are migrating some of our data services from Jersey 1.x using jersey-spring to Jersey 2.x using jersey-spring3. 我们正在使用泽西弹簧3将泽西1.x的一些数据服务从泽西1.x迁移到泽西2.x.

We have a few test classes that inherit from JerseyTest. 我们有一些继承自JerseyTest的测试类。 Some of these classes use custom applicationContext.xml files that are not specified in the web.xml file. 其中一些类使用未在web.xml文件中指定的自定义applicationContext.xml文件。

For object mocking purposes we would mock out some components in our Jersey Resources. 出于对象模拟的目的,我们将在Jersey资源中模拟一些组件。

In Jersey 1.x we could mock objects in the application context file by 在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>

and retrieve these mocked instances as follows 并按如下方式检索这些模拟的实例

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

How can the same be achieved with Jersey 2.x using jersey-spring3? 如何使用Jersey 2.x使用jersey-spring3实现同样的目标?

I have combed through the API docs , user guides and some of the sources but was unable to find an answer. 我已经梳理了API文档用户指南和一些来源,但无法找到答案。

Thank you. 谢谢。

EDIT: 编辑:

We will be using the mocked beans inside of our JAX-RS resources. 我们将在JAX-RS资源中使用模拟bean。 We have service interfaces that are @Autowired into our resources. 我们的服务接口已经@Autowired到我们的资源中。

eg 例如

@Path(ProductResource.RESOURCE_PATH)
@Component
@Scope("prototype")
public class ProductResource 
extends GenericResource<Product, BaseModel> {

    /*
     * Members
     */

    public static final String RESOURCE_PATH = "product/";

    @Autowired
    protected ProductService productService;

    ...

We want to mock out the and set the expectations on these services. 我们想要模拟并设定对这些服务的期望。

eg 例如

<bean id="productService" class="org.easymock.EasyMock" 
    factory-method="createStrictMock">
    <constructor-arg index="0" 
        value="com.xxx.xxx.service.ProductService" /> 
</bean>

Note: I am not a Spring expert and I consider this to be rather a work-around than a recommended approach. 注意:我不是Spring专家,我认为这是一种解决方案,而不是推荐的方法。 Hopefully someone will come up with a better solution. 希望有人会提出更好的解决方案。

You can't obtain an ApplicationContext instance by calling ContextLoader#getCurrentWebApplicationContext() because Jersey 2.x runtime is by default initialized outside of a Servlet container when using Jersey Test Framework ( JerseyTest ) for unit/e2e tests. 您无法通过调用ContextLoader#getCurrentWebApplicationContext()来获取ApplicationContext实例,因为在使用Jersey Test Framework( JerseyTest )进行单元/ e2e测试时,默认情况下将Jersey 2.x运行时初始化在Servlet容器之外。

In this case you need to use a little work-around to obtain an ApplicationContext by implementing an ApplicationContextAware interface in your test package: 在这种情况下,您需要通过在测试包中实现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;
    }
}

Once you have this class, don't forget to mention it in your application context descriptor: 有了这个类,不要忘记在应用程序上下文描述符中提及它:

...
<bean class="org.glassfish.jersey.examples.helloworld.spring.ApplicationContextUtils" />
...

And you can use it in your tests: 你可以在你的测试中使用它:

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

Note: If you want to deploy your application to a Servlet container and run your ( JerseyTest ) tests against it, consult Jersey Test Framework chapter in the Users Guide (especially External container section). 注意:如果要将应用程序部署到Servlet容器并针对它运行( JerseyTest )测试,请参阅“用户指南”(特别是外部容器部分)中的Jersey Test Framework一章。

You can inject your test class to Jersey context if you don't have any objections for that. 如果您对此没有任何异议,可以将测试类注入Jersey上下文。

For example: 例如:

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

After that the @Autowired annotation will work for you. 之后@Autowired注释将适合您。

For the Jersey 2.X users, here's what worked for me: 对于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);
    }

    ...
}

This allows me to use JavaConfig for my Jersey tests, and access the beans in the context as well. 这允许我使用JavaConfig进行Jersey测试,并在上下文中访问bean。 Here's the link to where I got the idea: http://geowarin.github.io/spring-boot/jersey/2014/01/31/a-simple-spring-boot-and-jersey-application.html 这是我得到这个想法的链接: http//geowarin.github.io/spring-boot/jersey/2014/01/31/a-simple-spring-boot-and-jersey-application.html

With Jersey version 2.4.x, the class JerseyConfiguration does not exist anymore and has been replaced by ResourceConfig which does not understand the contextConfig property. 使用Jersey版本2.4.x, JerseyConfiguration类不再存在,并且已被ResourceConfig取代,而ResourceConfig不理解contextConfig属性。 Here is my solution : 这是我的解决方案:

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 {
        ...
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM