2013-08-16 31 views
9

此問題是上一個問題Specify Custom Application Context的後續操作。使用jersey-spring3從JerseyTest容器中檢索托管bean

我們正在使用jersey-spring3將澤西島2.x的一些數據服務從Jersey 1.x遷移到Jersey 2.x。

我們有幾個從JerseyTest繼承的測試類。其中一些類使用未在web.xml文件中指定的自定義applicationContext.xml文件。

出於對象嘲諷的目的,我們會模擬出澤西島資源中的一些組件。

在新澤西1.x中,我們可以通過

<bean id="mockBean" class="org.easymock.EasyMock" 
    factory-method="createStrictMock" autowire="byName"> 
    <constructor-arg index="0" value="com.xxx.xxx.ClassToMock" /> 
</bean> 

嘲笑在應用程序上下文文件對象和如下

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

如何同與澤西2實現檢索這些嘲笑實例。 x使用jersey-spring3?

我已經梳理了API docs,user guides和一些sources,但無法找到答案。

謝謝。

編輯:

我們將使用我們的JAX-RS資源內的嘲笑豆。我們的服務接口是@Autowired加入我們的資源。

例如

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

    ... 

我們想嘲笑並設置對這些服務的期望。

例如

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

你能舉個例子嗎? (你如何/何時/你在哪裏使用mocked bean?它是否在JAX-RS資源內?)你確實需要'WebApplicationContext'還是任何'ApplicationContext'就足夠了? –

+0

「WebApplicationContext」或「ApplicationContext」都可以。哪一個會給我們一個指向注入JAX-RS資源的bean的指針。 –

回答

8

注:我不是一個Spring專家,我認爲這是比推薦的方法,而一個變通。希望有人會想出更好的解決方案。

您無法通過調用ContextLoader#getCurrentWebApplicationContext()因爲新澤西2.x的運行在默認情況下使用澤西測試框架(JerseyTest)爲單位/端對端測試時,一個Servlet容器外初始化獲得ApplicationContext實例。

在這種情況下,你需要使用一個小的變通在你的測試包實現一個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; 
    } 
} 

一旦你有了這個類,不要忘記提及它在應用程序上下文描述符:

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

而且你可以在你的測試中使用它:

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)測試,請查閱用戶手冊中(特別是External container部分)Jersey Test Framework章。

+0

感謝您的反饋。我會盡快給它進行測試。只是一個問題。不應該在'setApplicationContext'中'this.applicationContext = applicationContext'而應該'ApplicationContextUtils.applicationContext = applicationContext;'由於applicationContext是一個靜態字段。 –

+0

是的,固定的。謝謝。 –

+1

也可以在ApplicationContextUtils上使用'@Component'註釋(確保它位於組件掃描的包中),從而不需要顯式聲明bean。 –

1

澤西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爲我州的測試,並訪問豆類爲好。這裏的鏈接到我計上心來:http://geowarin.github.io/spring-boot/jersey/2014/01/31/a-simple-spring-boot-and-jersey-application.html

1

隨着新澤西版本2.4.x中,類JerseyConfiguration不存在了,並通過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 { 
     ... 
    } 
} 
3

如果你沒有任何反對意見,你可以注入你的測試類到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; 
} 

,此前@Autowired註釋會爲你工作。

+0

嗯,我們可以通過「contextConfigLocation」來告訴Jersey定製的Spring上下文文件,而不是默認的'applicationContext.xml'名稱。 – jediz