2013-08-16 2 views
9

Этот вопрос является следующим из предыдущего вопроса Specify Custom Application Context.Получить управляемый bean-компонент из контейнера JerseyTest с джерси-spring3

Мы переносим некоторые из наших служб передачи данных с Джерси 1.x, используя Джерси-весну на Джерси 2.x, используя джерси-spring3.

У нас есть несколько тестовых классов, которые наследуются от JerseyTest. Некоторые из этих классов используют пользовательские файлы applicationContext.xml, которые не указаны в файле web.xml.

Для объективных издевательских целей мы будем издеваться над некоторыми компонентами в наших ресурсах 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> 

и получить эти издевались экземпляры следующим

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

Как можно же быть достигнуто с Джерси 2. x используя трикотаж-весна3?

Я прочесал через API docs, user guides и некоторые из sources, но не смог найти ответа.

спасибо.

EDIT:

Мы будем использовать издевались бобы внутри наших 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

Можете ли вы проиллюстрировать это на примере? (Как/Когда/Где вы используете фальшивый компонент? Это внутри ресурса JAX-RS?) Вам нужно точно «WebApplicationContext» или любой «ApplicationContext» достаточно? –

+0

Либо «WebApplicationContext», либо «ApplicationContext» будет в порядке. Который когда-либо дал бы нам указатель на компонент, который был введен в ресурсы JAX-RS. –

ответ

8

Примечание: Я не эксперт весна, и я считаю, что это скорее обходным, чем рекомендуемый подход. Надеюсь, кто-то придумает лучшее решение.

Вы не можете получить ApplicationContext экземпляр, вызвав ContextLoader#getCurrentWebApplicationContext(), потому что Джерси 2.x выполнения по умолчанию инициализируется за пределами Servlet контейнера при использовании Джерси Framework Test (JerseyTest) для блока/E2e испытаний.

В этом случае вам нужно использовать немного работы вокруг, чтобы получить ApplicationContext путем реализации интерфейса ApplicationContextAware в тестовом пакете:

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

Примечание: Если вы хотите, чтобы развернуть приложение в контейнер сервлетов и запустить (JerseyTest) испытания против него, обратитесь Jersey Test Framework главу в Руководстве пользователя (особенно External container раздел).

+0

Благодарим вас за отзыв. Я дам ему тест, как только смогу. Только один вопрос. Не должно быть 'this.applicationContext = applicationContext;' в 'setApplicationContext' скорее быть' ApplicationContextUtils.applicationContext = applicationContext; 'видя как applicationContext является статическим полем. –

+0

Да, исправлено. Благодарю. –

+1

Можно также использовать аннотацию @Component на ApplicationContextUtils (гарантируя, что она находится в пакете, который проверяется компонентом), тем самым избавляясь от необходимости явно объявлять компонент. –

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

Вы можете ввести свой тестовый класс в контекст Джерси, если у вас нет никаких возражений.

Например:

@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

Ах, мы можем сказать Джерси, какой пользовательский контекстный файл Spring искать по ссылке «contextConfigLocation» вместо имени «applicationContext.xml» по умолчанию. – jediz

Смежные вопросы