2014-07-01 16 views
8

Bir Test'i JerseyTest ile test etmek istiyorum. Aşağıdaki testi oluşturduk:Forma Forması, JerseyTest'ten atasözlerini okumak için

@RunWith(SpringJUnit4ClassRunner.class) 
@ContextConfiguration(locations = "classpath:testApplicationContext.xml") 
public class ResourceTest extends JerseyTest 
{ 
    @Configuration 
    public static class Config 
    { 
     @Bean 
     public AObject aObject() 
     { 
      return mock(AObject.class); 
     } 
    } 

    @Autowired 
    public AObject _aObject; 

    @Test 
    public void testResource() 
    { 
     // configouring mock _aObject 

     Response response = target("path"); 
     Assert.assertEquals(Response.Status.OK.getStatusCode(), response.getStatus()); 
    } 


    @Override 
    protected Application configure() 
    { 
     return new ResourceConfig(Resource.class).property("contextConfigLocation", "classpath:testApplicationContext.xml"); 
    } 
} 

My Kaynak ayrıca @Autowired açıklama ile bir AObject referansı vardır.

Benim sorunum, JerseyTest ve Resource (sınama tarafından yapılandırılan) benim Mock nesnesi için farklı örneklere sahip olmasıdır. Konsolda testApplicationContext.xml'un iki kez, bir kez test için ve bir tane Kaynak için yüklendiğini görüyorum.

Jersey'i aynı sahtekarlığı kullanmaya nasıl zorlayabilirim?

cevap

15

(sürüm 2.9.1) kütüphane forması-spring3 ayıklama sonra sorun SpringComponentProvider.createSpringContext yatıyor görünüyor

private ApplicationContext createSpringContext() { 
    ApplicationHandler applicationHandler = locator.getService(ApplicationHandler.class); 
    ApplicationContext springContext = (ApplicationContext) applicationHandler.getConfiguration().getProperty(PARAM_SPRING_CONTEXT); 
    if (springContext == null) { 
     String contextConfigLocation = (String) applicationHandler.getConfiguration().getProperty(PARAM_CONTEXT_CONFIG_LOCATION); 
     springContext = createXmlSpringConfiguration(contextConfigLocation); 
    } 
    return springContext; 
} 

Kontrol edildi "contextConfig" adlı bir özellik uygulama özelliklerinde varsa ve değilse, yay uygulama içeriğini başlatır. Testlerinizde bir yay uygulama bağlamı başlatmış olsanız bile, jersey başka bir bağlam oluşturacak ve bunun yerine kullanacaktır. Yani, bir şekilde ApplicationContext'i Jersey Uygulama sınıfındaki testlerimizden geçmek zorundayız.

@ContextConfiguration(locations = "classpath:jersey-spring-applicationContext.xml") 
public abstract class JerseySpringTest 
{ 
    private JerseyTest _jerseyTest; 

    public final WebTarget target(final String path) 
    { 
     return _jerseyTest.target(path); 
    } 

    @Before 
    public void setup() throws Exception 
    { 
     _jerseyTest.setUp(); 
    } 

    @After 
    public void tearDown() throws Exception 
    { 
     _jerseyTest.tearDown(); 
    } 

    @Autowired 
    public void setApplicationContext(final ApplicationContext context) 
    { 
     _jerseyTest = new JerseyTest() 
     { 
      @Override 
      protected Application configure() 
      { 
       ResourceConfig application = JerseySpringTest.this.configure(); 
       application.property("contextConfig", context); 

       return application; 
      } 
     }; 
    } 

    protected abstract ResourceConfig configure(); 
} 

yukarıdaki sınıf testlerimizden uygulama bağlamını alıp SpringComponentProvider formanın aynı uygulama bağlamı dönecektir böylece yapılandırılmış ResourceConfig iletecek: Çözüm şudur. Jersey özel yay yapılandırmasını içermek için jersey-spring-applicationContext.xml'i de kullanıyoruz.

Test uygulama içeriği başlatılmadan önce Uygulamayı yapıcıda başlattığı için JerseyTest'ten miras taşıyamayız.

Artık sahte AObject enjekte etmek amacıyla şu tanımı eklemek testContext.xml olarak örnek

@RunWith(SpringJUnit4ClassRunner.class) 
@ContextConfiguration(locations = "classpath:testContext.xml") 
public class SomeTest extends JerseySpringTest 
{ 
    @Autowired 
    private AObject _aObject; 

    @Test 
    public void test() 
    { 
      // configure mock _aObject when(_aObject.method()).thenReturn() etc... 

     Response response = target("api/method").request(MediaType.APPLICATION_JSON).get(); 
     Assert.assertEquals(Response.Status.OK.getStatusCode(), response.getStatus()); 
    } 

    @Override 
    protected ResourceConfig configure() 
    { 
     return new ResourceConfig(MyResource.class); 
    } 
} 

için testleri oluşturmak için bu temel sınıfını kullanabilirsiniz.

<bean class="org.mockito.Mockito" factory-method="mock"> 
    <constructor-arg value="com.yourcompany.AObject" /> 
</bean> 
+1

Harika cevap! Teşekkürler –

+0

Bu cevap için çok teşekkür ederim, jersey test framework ve spring-test ile entegrasyon testleri geliştirmek için benim sorunları çözer. Özellikle benim problemim, aynı ApplicationContext'te test yürütmesi sırasında sahte nesneleri öğretmekti. Her şey için teşekkürler, – bifulcoluigi

1

o neden oluyor için yaptığı açıklama doğru olmasına rağmen ben, çalışma @Grigoris cevabını https://stackoverflow.com/a/24512682/156477 alamadım. Sonunda, alay nesnesini yerleştirmek için özel bir ayarlayıcı ortaya koyan aşağıdaki yaklaşıma gittim. Değil ..

public MyAPITest extends JerseyTest { 

    // Declare instance of the API I want to test - this will be instantiated in configure() 
    MyAPI myAPI; 

    @Override 
    protected ResourceConfig configure() 
    { 
     MockitoAnnotations.initMocks(this); 
     myAPI = new MyAPI(); 

     ResourceConfig resourceConfig = new ResourceConfig(); 
     resourceConfig.register(MyAPI).property("contextConfig", new ClassPathXmlApplicationContext("classpath:spring.testHarnessContext.xml")); 
     return resourceConfig; 
    } 

    @Mock 
    private MyAPIProvider mockAPIProvider; 

    @Before 
    public void before() { 
     myAPI.setMockProvider(mockAPIProvider); 
    } 


    @Test 
    public void test() { 

     // I can now define the mock behaviours and call the API and validate the outcomes 
     when(mockAPIProvider....) 
     target().path("....)    
    } 
} 
0

kimse Jersey v1 için Kevin'den solüsyon https://stackoverflow.com/a/40591082/4894900 ilgilenen varsa bazı testler yazabilirsiniz yüzden alay istedim apiProvider açığa tradeoff yukarıdaki yaklaşım olarak 'temiz' ama değer olarak :

public MyAPITest extends JerseyTest { 

    @InjectMocks 
    MyAPI myAPI; 

    @Mock 
    MyApiService myApiService; 

    @Override 
    protected AppDescriptorconfigure() 
    { 
     MockitoAnnotations.initMocks(this); 

     ResourceConfig rc = new DefaultResourceConfig(); 
     rc.getSingletons().add(myAPI); 

     return new LowLevelAppDescriptor.Builder(rc).contextPath("context").build(); 
    } 

    @Test 
    public void test() { 
     // I can now define the mock behaviours 
     when(myApiService...) 

     WebResource webResource = resource().path("mypath"); 
     ClientResponse result = webResource.get(ClientResponse.class);    
    } 
}