2016-06-09 9 views
6

मैंने ऑनलाइन खोज करने में काफी कुछ किया है और मुझे एक ऑटोवायर कन्स्ट्रक्टर के साथ यूनिट परीक्षण का उदाहरण नहीं मिल रहा है। मैं एक प्रॉपर्टी फ़ाइल से अपने आवेदन में मूल्यों में ऑटोवायर करने के लिए वसंत का उपयोग कर रहा हूं। मैं MyApp.java की स्टार्ट विधि का परीक्षण करना चाहता हूं, लेकिन मेरे पास एक ऑटोवायर कन्स्ट्रक्टर है इसलिए मुझे नहीं पता कि MyApp को कैसे चालू किया जाए। autowired गुण के बिना, मैं अपने इकाई परीक्षण में यह कर रहा था:मैं एक स्प्रिंग ऑटोवायर कन्स्ट्रक्टर का परीक्षण कैसे करूं?

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

मैं नहीं चाहता कि autowiring उपहास करने के लिए, जैसा कि मैंने से गुण फ़ाइल और चीजों को आगे जटिल मान प्राप्त करने की जरूरत है, चाहता हूँ मैं कर रहा हूँ एनोटेशन के माध्यम से सब कुछ विन्यस्त करना। मेरे पास spring.xml, application-context.xml, या web.xml फ़ाइल नहीं है। तो मैं MyApp की प्रारंभ विधि को तत्काल/परीक्षण करने के बारे में कैसे जा सकता हूं? मैंने @RunWith (SpringJUnit4ClassRunner.class) में जोड़ने और MyApp myApp को स्वचालित करने की कोशिश की, लेकिन यह उस एप्लिकेशन संदर्भ को लोड करने में विफल होने के बारे में त्रुटियों को फेंकता है जो परीक्षण कक्षा पर ApplicationContextAware को लागू करके तय नहीं किया गया है।

यहाँ MyApp.java है

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

यहाँ मेरी app.properties फ़ाइल है

# Spring Configuration for My application 

#properties for the embedded jetty server 
http_server_port=12345 

यहाँ MyAppProperties.java

@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 है

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

अद्यतन: यहाँ मेरी विन्यास वर्ग

@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

केवल '@ रनविथ' जोड़ना और बिना कॉन्फ़िगरेशन को लोड करने के बारे में बताएगा विफल हो जाएगा। आपको अपनी टेस्ट क्लास में 'सार्वजनिक कॉन्फ़िगरेशन क्लास 'को' कॉन्फ़िगरेशन 'और' कॉम्पोनेंटस्कैन (" your.package ") पर रखना होगा। एक और स्तर पर मैं सुझाव देता हूं कि स्प्रिंग बूट का उपयोग आपके एप्लिकेशन को बूटस्ट्रैप भी करें और गुणों का इंजेक्ट करें/उपयोग करें क्योंकि आप वास्तव में ऐसा कर रहे हैं जो स्प्रिंग बूट आउट ऑफ़ द बॉक्स (इसके लिए टेस्ट सपोर्ट सहित) प्रदान करता है। –

+0

@ एम। डीनियम दुर्भाग्य से, अन्य उपकरणों के साथ संघर्ष के कारण स्प्रिंग बूट मेरे लिए एक विकल्प नहीं है। बस स्पष्ट करने के लिए आप कह रहे हैं कि मुझे अपनी टेस्ट क्लास को सार्वजनिक स्थैतिक वर्ग MyAppTest बनना चाहिए या क्या मुझे एक और कक्षा बनाना है? जब मैं MyAppTest क्लास स्थिर बनाने की कोशिश करता हूं तो मुझे एक त्रुटि संदेश मिलता है जिसमें कहा गया है कि यह एक अवैध संशोधक है। – jencoston

+0

नहीं, आपको आंतरिक कॉन्फ़िगरेशन क्लास जोड़ने की आवश्यकता है।इसके अलावा मुझे एक आंतरिक सर्वर को हंसने के साथ स्प्रिंग बूट क्या करता है, इसमें कोई अंतर नहीं दिखता है, वास्तव में कोई अंतर नहीं होना चाहिए। –

उत्तर

6

हम jmockito ढांचे का उपयोग कर वस्तुओं नकली कर सकते हैं। Mockito के माध्यम से निर्भरता इंजेक्शन के लिए

का उपयोग @InjectMocks तुम भी @InjectMocks एनोटेशन जो प्रकार के आधार पर निर्माता, विधि या क्षेत्र निर्भरता इंजेक्शन करने की कोशिश करता है। निम्नलिखित कोड जावाडोक से थोड़ा संशोधित उदाहरण है।

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

निम्नलिखित यूनिट टेस्ट क्लास होगा।

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

}

सुनिश्चित करें कि आप @RunWith (MockitoJUnitRunner.class) अधिक जानकारी के लिए http://docs.mockito.googlecode.com/hg/1.9.5/org/mockito/InjectMocks.html देख उपयोग कर रहे हैं।

+0

उत्तर के लिए धन्यवाद! यदि मैं MyApp कन्स्ट्रक्टर का नकल करता हूं तो क्या मैं अभी भी गुण फ़ाइल से मान प्राप्त कर रहा हूं? जिस विधि को मैं परीक्षण करने का प्रयास कर रहा हूं वह एम्बेडेड जेट्टी सर्वर शुरू करता है और इसे करने के लिए इसे गुण फ़ाइल से मान प्राप्त करने की आवश्यकता होती है। @InjectMocks का उपयोग कर – jencoston

+0

को एक बुरा अभ्यास माना जाता है। देखें, उदाहरण के लिए: https://lkrnac.net/blog/2014/02/promoting-constructor-field-injection/ – JonyD

+0

@JonyD टिप्पणी के बारे में: मैंने कुछ टिप्पणियां पढ़ी हैं और उनमें से अधिकांश लेख का खंडन करते हैं। क्या आपको कुछ अंतिम जवाब मिला है? – matthieusb

संबंधित मुद्दे