2016-06-09 21 views
6

Online olarak biraz arama yaptım ve otomatikleştirilmiş bir kurucu ile birim testi örneği bulamıyorum. Bir özellik dosyasındaki değerleri uygulamamda otomatik olarak yönlendirmek için Spring kullanıyorum. Birim testi MyApp.java'nın başlangıç ​​yöntemini kullanmak istiyorum, ancak otomatikleştirilmiş bir kurucum var, böylece Uygulamam'ı nasıl oluşturacağımı bilmiyorum. autowired özellikleri olmasa, benim birim testinde bu yapıyordu: Ben özellikleri şeyleri dosya ve daha fazla zorlaştırmak için değerleri almak gerekir olarakJUnit, Spring otomatik kablolu yapıcısını nasıl test edebilirim?

@Test 
public void testStart() { 
    try{ 
    MyApp myApp = new MyApp(); 
    myApp.start(); 
    } 
    catch (Exception e){ 
    fail("Error thrown") 
    } 
} 

Ben namuslu, Autowiring alay etmek istemiyoruz ek açıklamalarla her şeyi yapılandırmak. Bir spring.xml, application-context.xml veya bir web.xml dosyası yok. Peki, MyApp'ın başlangıç ​​yöntemini başlatmayı/test etmeyi nasıl başarabilirim? @RunWith (SpringJUnit4ClassRunner.class) ve MyApp myApp'ı otomatik olarak eklemeyi denedim, ancak uygulama sınıfında ApplicationContextAware uygulanarak düzeltilmeyen uygulama bağlamını yükleme konusunda hatalar atıyor. İşte

İşte

@Component 
public class MyApp { 

    private static ApplicationContext applicationContext; 
    private static MyAppProperties myAppProperties; 

    //Obtain the values from the app.properties file 
    @Autowired 
    MyApp(MyAppProperties myAppProps){ 
     myAppProperties = myAppProps; 
    } 

    public static void main(String[] args) throws Exception { 
    // Instantiate the application context for use by the other classes 
    applicationContext = new AnnotationConfigApplicationContext("com.my.company"); 

    start(); 
    } 

    /** 
    * Start the Jetty server and configure the servlets 
    * 
    * @throws Exception 
    */ 
    public static void start() throws Exception { 
     // Create Embedded Jetty server 
     jettyServer = new Server(); 

     // Configure Jetty so that it stops at JVM shutdown phase 
     jettyServer.setStopAtShutdown(true); 
     jettyServer.setStopTimeout(7_000); 

     // Create a list to hold all of the handlers 
     final HandlerList handlerList = new HandlerList(); 

     // Configure for Http 
     HttpConfiguration http_config = new HttpConfiguration(); 
     http_config.setSecureScheme("https"); 
     http_config.setSecurePort(myAppProperties.getHTTP_SECURE_PORT()); 
    .... 
    } 
} 

benim app.properties

İşte
# Spring Configuration for My application 

#properties for the embedded jetty server 
http_server_port=12345 

İşte

@Component 
public class MyAppProperties implements ApplicationContextAware { 

    private ApplicationContext applicationContext; 

    //List of values from the properties files to be autowired 
    private int HTTP_SERVER_PORT; 
    ... 

    @Autowired 
    public MyAppProperties(@Value("${http_server_port}") int http_server_port, ...){ 
     this.HTTP_SERVER_PORT = http_server_port; 
    } 

    /** 
    * @return the applicationContext 
    */ 
    public ApplicationContext getApplicationContext() { 
     return applicationContext; 
    } 

    /** 
    * @param applicationContext 
    *   the applicationContext to set 
    */ 
    @Override 
    public void setApplicationContext(ApplicationContext applicationContext) { 
     this.applicationContext = applicationContext; 
    } 

    /** 
    * @param name 
    *   the name to set 
    */ 
    public void setHTTP_SERVER_PORT(String name) { 
     JETTY_SERVER_NAME = name; 
    } 

    /** 
    * @return the httpServerPort 
    */ 
    public int getHTTP_SERVER_PORT() { 
     return HTTP_SERVER_PORT; 
    } 
} 

MyAppTest.java olan MyAppProperties.java olduğu dosya olduğu MyApp.java olan

@RunWith(SpringJUnit4ClassRunner.class) 
public class MyAppTest implements ApplicationContextAware{ 

    private ApplicationContext applicationContext; 

    @Override 
    public void setApplicationContext(ApplicationContext appContext) { 
     applicationContext = appContext;  
    } 

    @Autowired 
    private MyApp myapp; 

    @Test 
    public void testStart(){ 
    try { 
     if(myapp != null){ 
      myapp.start(); 
     } 
     else{ 
      fail("myapp is null"); 
     } 
    } catch (Exception e) { 
     fail("Error thrown"); 
     e.printStackTrace(); 
    } 
    } 
} 

GÜNCELLEME: İşte Biz jmockito çerçevesini kullanarak nesneleri taklit benim yapılandırma sınıfı

@Configuration 
@Component 
public class ApplicationConfig implements ApplicationContextAware { 

    private final Logger LOGGER = LoggerFactory.getLogger(ApplicationConfig.class); 
    private ApplicationContext applicationContext; 

    /** 
    * @return the applicationContext 
    */ 
    public ApplicationContext getApplicationContext() { 
     LOGGER.debug("Getting Application Context", applicationContext); 
     return applicationContext; 
    } 

    /** 
    * @param applicationContext 
    *   the applicationContext to set 
    */ 
    @Override 
    public void setApplicationContext(ApplicationContext applicationContext) { 
     this.applicationContext = applicationContext; 
    } 

    // Needed for @Value 
    /** 
    * Property sources placeholder configurer. 
    * 
    * @return the property sources placeholder configurer 
    */ 
    @Bean 
    public PropertyPlaceholderConfigurer getPropertyPlaceholderConfigurer() { 
     PropertyPlaceholderConfigurer propertyPlaceholderConfigurer = new PropertyPlaceholderConfigurer(); 
     propertyPlaceholderConfigurer.setLocation(new ClassPathResource("app.properties")); 
     return propertyPlaceholderConfigurer; 
    } 
    ... 
} 
+0

Sadece @ RunWith'i eklemek ve hangi yapılandırmanın yükleneceğini belirtmeden söyleyin. Test sınıfınıza '@ Configuration 've' @ComponentScan (' your.package ') 'koymak için' public static class' eklemeniz gerekir. Daha ileri düzeyde Spring Boot'u uygulamanızı önyüklemenizi ve Spring Boot'un kullanıma hazır olarak (test desteği de dahil olmak üzere) tam olarak ne yaptığını görünce enjekte/kullanım özelliklerini kullanmanızı öneriyorum. –

+0

@ M.Deinum Ne yazık ki, Spring Boot diğer araçlar ile çakışmaları nedeniyle benim için bir seçenek değil. Sadece açıklığa kavuşturmak için benim test sınıfımın genel statik sınıf MyAppTest olması için değiştirmem gerektiğini mi söylüyorsun yoksa başka bir ders mi yapmam gerekiyor? MyAppTest sınıfını statik yapmaya çalıştığımda, bunun yasal olmayan bir değiştirici olduğunu belirten bir hata iletisi alıyorum. – jencoston

+0

Hayır Dahili bir konfigürasyon sınıfı eklemeniz gerek.Ayrıca, Spring Boot'un kendiniz yaptığınız gibi bir iç sunucuya güldüğü ile ilgili hiçbir fark görmüyorum, gerçekten bir fark olmamalı. –

cevap

6

olduğunu. Mockito yoluyla bağımlılık enjeksiyon için

kullanma @InjectMocks Ayrıca türüne göre yapıcı, yöntem veya alan bağımlılık enjeksiyon yapmaya çalışır @InjectMocks ek açıklama var. Aşağıdaki kod Javadoc'tan biraz değiştirilmiş bir örnektir.

// Mockito can construct this class via constructor public class ArticleManager { ArticleManager(ArticleCalculator calculator, ArticleDatabase database) { } } // Mockito can also perform method injection public class ArticleManager { ArticleManager() { } void setDatabase(ArticleDatabase database) { } void setCalculator(ArticleCalculator calculator) { } } // Mockito can also perform field injection public class ArticleManager { private ArticleDatabase database; private ArticleCalculator calculator; } 

Aşağıdakiler birim test sınıfı olacaktır.

@RunWith(MockitoJUnitRunner.class) 
public class ArticleManagerTest { 
    @Mock private ArticleCalculator calculator; 
    @Mock private ArticleDatabase database; 
    @Spy private UserProvider userProvider = new ConsumerUserProvider(); 

    // creates instance of ArticleManager 
    // and performs constructor injection on it 
    @InjectMocks private ArticleManager manager; 

    @Test public void shouldDoSomething() { 
      // assume that ArticleManager has a method called initialize which calls a method 
      // addListener with an instance of ArticleListener 
      manager.initialize(); 

     // validate that addListener was called 
      verify(database).addListener(any(ArticleListener.class)); 
    } 

}

Eğer @RunWith (MockitoJUnitRunner.class) Daha fazla bilgi için http://docs.mockito.googlecode.com/hg/1.9.5/org/mockito/InjectMocks.html bkz kullandığınızdan emin olun.

+0

Cevabınız için teşekkür ederiz! MyApp kurucusuna alay edersem, yine de özellikler dosyasındaki değerleri alacağım mı? Test etmeye çalıştığım yöntem gömülü iskele sunucusunu başlatır ve bunu yapmak için özellikler dosyasından değerler alması gerekir. @InjectMocks kullanarak – jencoston

+0

kötü bir uygulama olarak kabul edilir. bkz., örneğin: https://lkrnac.net/blog/2014/02/promoting-constructor-field-injection/ – JonyD

+0

@JonyD hakkında Yorum: Birkaç yorum okudum ve çoğu makaleyle çelişiyor. Son cevapları buldunuz mu? – matthieusb