जूनियर टेस्ट कक्षाओं में पुन: उपयोग वसंत आवेदन संदर्भ


84

हमने JUnit परीक्षण मामलों (एकीकरण परीक्षण) का एक समूह बनाया है और वे तार्किक रूप से अलग-अलग परीक्षण कक्षाओं में वर्गीकृत किए गए हैं।

हम परीक्षण वर्ग के अनुसार एक बार स्प्रिंग एप्लिकेशन के संदर्भ को लोड करने में सक्षम हैं और इसे JUnit परीक्षण वर्ग के सभी परीक्षण मामलों के लिए फिर से उपयोग कर सकते हैं, जैसा कि http://static.springsource.org/spring/docs/current/spring-framework-reference में उल्लेख किया गया है। /html/testing.html

हालांकि, हम सिर्फ यह सोच रहे थे कि क्या JUnit टेस्ट कक्षाओं के एक समूह के लिए केवल एक बार स्प्रिंग एप्लिकेशन संदर्भ लोड करने का कोई तरीका है।

FWIW, हम स्प्रिंग 3.0.5, JUnit 4.5 का उपयोग करते हैं और प्रोजेक्ट बनाने के लिए मावेन का उपयोग करते हैं।


5
नीचे दिए गए सभी उत्तर महान हैं, लेकिन मेरे पास एक संदर्भ नहीं है। xml। क्या मैंने गुमनामी में अपना रास्ता बदल दिया है? रेफरेंस के बिना ऐसा करने का कोई तरीका। xml?
markthegrea

2
क्या आपको अपने समाधान का उत्तर मिला? मैं एक ही समस्या है और मैं एनोटेशन और स्प्रिंग बूट के साथ यह करना चाहते हैं।
अलेक्जेंडर

जवाबों:


96

हां, यह पूरी तरह से संभव है। आपको बस इतना करना है कि locationsअपनी परीक्षा कक्षाओं में उसी विशेषता का उपयोग करें :

@ContextConfiguration(locations = "classpath:test-context.xml")

स्प्रिंग कैश एप्लिकेशन संदर्भों को locationsविशेषता के आधार पर locationsप्रदर्शित करता है, इसलिए यदि दूसरी बार ऐसा प्रतीत होता है, तो स्प्रिंग नया बनाने के बजाय उसी संदर्भ का उपयोग करता है।

मैंने इस विशेषता के बारे में एक लेख लिखा है: स्प्रिंग एकीकरण परीक्षणों को गति देना । साथ ही इसे स्प्रिंग डॉक्यूमेंटेशन में विवरण में वर्णित किया गया है: 9.3.2.1 संदर्भ प्रबंधन और कैशिंग

इसका एक दिलचस्प निहितार्थ है। क्योंकि वसंत को पता नहीं है कि जब जुनाइट किया जाता है, तो यह सभी संदर्भों को हमेशा के लिए कैश कर देता है और जेवीएम शटडाउन हुक का उपयोग करके उन्हें बंद कर देता है। यह व्यवहार (विशेष रूप से जब आपके पास विभिन्न के साथ बहुत अधिक परीक्षण कक्षाएं होती हैं locations) तो अत्यधिक मेमोरी उपयोग, मेमोरी लीक आदि हो सकती हैं, कैशिंग संदर्भ का एक और फायदा।


आह! इसका एहसास नहीं हुआ। हम लंबे समय से इस दृष्टिकोण का पालन कर रहे हैं और मैंने (गलती से) प्रत्येक परीक्षण वर्ग के साथ वसंत संदर्भ लोड करने के लिए परीक्षण निष्पादन के लिए लंबी अवधि को जिम्मेदार ठहराया है। अब ध्यान से जांच करेंगे। धन्यवाद।
रमेश

1
मैं यह कहूंगा कि वसंत को आपके टेस्टेस के निष्पादन के आदेश के बारे में कोई जानकारी नहीं है। इसके परिणामस्वरूप यह नहीं बताया जा सकता है कि क्या संदर्भ बाद में आवश्यक है, या इसका निपटान किया जा सकता है।
philnate

1
मैं नहीं देखता कि यह वास्तव में कैसे सच हो सकता है। हर बार जब मैं एक रन ऐस / ज्यूनीट टेस्ट करता हूं, तो ग्रहण / जेयूनेट पर्यावरण को क्रैंक करने में 2 मिनट खर्च करता है। अगर कुछ भी कैश नहीं होता तो ऐसा नहीं होता।
user1944491

3
किसी भी विचार अगर यह संदर्भ परिभाषा के लिए एक XML का उपयोग करने के बजाय एनोटेशन के माध्यम से पूरी तरह से किया जा सकता है? मैंने इसके बारे में डॉक्टर और यहाँ एसओ पर बहुत खोज की है, लेकिन ऐसा कुछ भी नहीं मिला जो मुझे लगता है कि यह संभव नहीं है।
जीन-फ्रांस्वा सवार्ड

यदि आपके पास इनिशियलाइज़र है तो क्या यह सही नहीं है? मेरा कक्षा में हर परीक्षा के लिए इनिशियलाइज़ेशन हो रहा है
कल्पेश सोनी

26

टॉमाज़ नर्कविक्ज़ के उत्तर में जोड़ने के लिए , स्प्रिंग 3.2.2 @ContextHierarchyएनोटेशन के रूप में अलग-अलग, संबंधित संरचना संरचना का उपयोग किया जा सकता है। यह तब सहायक होता है जब कई परीक्षण कक्षाएं स्मृति डेटाबेस सेटअप (डेटा स्रोत, EntityManagerFactory, tx प्रबंधक आदि) में साझा करना चाहती हैं (उदाहरण के लिए)।

उदाहरण के लिए:

@ContextHierarchy({
  @ContextConfiguration("/test-db-setup-context.xml"),
  @ContextConfiguration("FirstTest-context.xml")
})
@RunWith(SpringJUnit4ClassRunner.class)
public class FirstTest {
 ...
}

@ContextHierarchy({
  @ContextConfiguration("/test-db-setup-context.xml"),
  @ContextConfiguration("SecondTest-context.xml")
})
@RunWith(SpringJUnit4ClassRunner.class)
public class SecondTest {
 ...
}

इस सेटअप के होने से "टेस्ट-डीबी-सेटअप-संदर्भ.एक्सएमएल" का उपयोग करने वाला संदर्भ केवल एक बार बनाया जाएगा, लेकिन इसके अंदर सेम को व्यक्तिगत इकाई परीक्षण के संदर्भ में इंजेक्ट किया जा सकता है

मैनुअल पर अधिक: http://docs.spring.io/spring/docs/current/spring-framework-reference/html/testing.html#testcontext-ctx-management (इस संदर्भ पदानुक्रम के लिए खोज ")


मेरे पास मल्टी-मॉड्यूल मावेन है, और मैं सेवा मॉड्यूल में डेटाबेस सेटअप से बचने की कोशिश करता हूं (क्योंकि यह पहले से ही डेटाकेस मॉड्यूल के परीक्षणों से भरा हुआ है) और यह मेरे लिए काम नहीं करता है!
मुहम्मद Hewedy

5
यह मेरे लिए काम किया! धन्यवाद। बस स्पष्ट होने के लिए, @ कॉन्टेक्स्ट हियरार्की एनोटेशन के बिना, वसंत प्रत्येक परीक्षण के लिए मेरे डीबी को लोड करता है। मैं "क्लासेस" का उपयोग कर रहा हूँ परम: @ContextConfiguration (classes = {JpaConfigTest.class, ...
Brel

5
किसी भी विचार अगर यह संदर्भ परिभाषा के लिए एक XML का उपयोग करने के बजाय एनोटेशन के माध्यम से पूरी तरह से किया जा सकता है? मैंने इसके बारे में डॉक्टर और यहाँ एसओ पर बहुत खोज की है, लेकिन ऐसा कुछ भी नहीं मिला जो मुझे लगता है कि यह संभव नहीं है।
जीन-फ्रांस्वा सवार्ड

1
@ जीन-फ्रांस्वास्वार्ड क्या आपकी खोजों में कोई भाग्य था (एक्सएमएल के बजाय एनोटेशनस्वा के माध्यम से)?
javadev

@javadev मैं इस आशा है कि आप के लिए क्या देख रहे है docs.spring.io/spring/docs/current/spring-framework-reference/...
Raviteja Gubba

1

मूल रूप से वसंत आपके लिए इसे कॉन्फ़िगर करने के लिए पर्याप्त स्मार्ट है यदि आपके पास विभिन्न टेस्ट कक्षाओं में एक ही एप्लिकेशन संदर्भ कॉन्फ़िगरेशन है। उदाहरण के लिए मान लें कि आपके पास ए और बी दो वर्ग हैं:

@ActiveProfiles("h2")
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class A {

    @MockBean
    private C c;
    //Autowired fields, test cases etc...
}

@ActiveProfiles("h2")
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class B {

    @MockBean
    private D d;
    //Autowired fields, test cases etc...
}

इस उदाहरण में क्लास ए मोक्स बीन सी, जबकि क्लास बी मोक्स बीन डी। तो, स्प्रिंग इन्हें दो अलग-अलग कॉन्फ़िगरेशन मानते हैं और इस तरह क्लास ए के लिए एक बार और क्लास बी के लिए एक बार आवेदन के संदर्भ को लोड करेंगे।

यदि इसके बजाय, हम चाहते हैं कि वसंत इन दो वर्गों के बीच अनुप्रयोग संदर्भ साझा करे, तो उन्हें कुछ इस प्रकार देखना होगा:

@ActiveProfiles("h2")
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class A {

    @MockBean
    private C c;

    @MockBean
    private D d;
    //Autowired fields, test cases etc...
}

@ActiveProfiles("h2")
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class B {

    @MockBean
    private C c;

    @MockBean
    private D d;
    //Autowired fields, test cases etc...
}

यदि आप अपनी कक्षाओं को इस तरह से तार करते हैं, तो वसंत केवल एक बार या तो कक्षा ए या बी के लिए आवेदन के संदर्भ को लोड करेगा, इस पर निर्भर करता है कि दोनों में से कौन सा वर्ग पहले परीक्षण सूट में चला गया है। इसे कई परीक्षण कक्षाओं में दोहराया जा सकता है, केवल मानदंड यह है कि आपको परीक्षण कक्षाओं को अलग तरीके से अनुकूलित नहीं करना चाहिए। कोई भी अनुकूलन जिसके परिणामस्वरूप परीक्षण वर्ग दूसरे (वसंत की आंखों में) से अलग होता है, वसंत द्वारा एक और अनुप्रयोग संदर्भ बनाता है।


0

नीचे की तरह अपना विन्यास वर्ग बनाएं

@ActiveProfiles("local")
@RunWith(SpringJUnit4ClassRunner.class )
@SpringBootTest(classes ={add your spring beans configuration classess})
@TestPropertySource(properties = {"spring.config.location=classpath:application"})
@ContextConfiguration(initializers = ConfigFileApplicationContextInitializer.class)
public class RunConfigration {

    private ClassLoader classloader = Thread.currentThread().getContextClassLoader();

    private static final Logger LOG = LoggerFactory.getLogger(S2BXISINServiceTest.class);


    //auto wire all the beans you wanted to use in your test classes
    @Autowired
    public XYZ xyz;
    @Autowired
    public ABC abc;


    }



Create your test suite like below



@RunWith(Suite.class)
@Suite.SuiteClasses({Test1.class,test2.class})
public class TestSuite extends RunConfigration {

    private ClassLoader classloader = Thread.currentThread().getContextClassLoader();

    private static final Logger LOG = LoggerFactory.getLogger(TestSuite.class);


}

अपनी परीक्षा कक्षाएं नीचे की तरह बनाएं

public class Test1 extends RunConfigration {


  @Test
    public void test1()
    {
    you can use autowired beans of RunConfigration classes here 
    }

}


public class Test2a extends RunConfigration {

     @Test
    public void test2()
    {
    you can use autowired beans of RunConfigration classes here 
    }


}

0

एक उल्लेखनीय बात यह है कि यदि हम @SpringBootTests का उपयोग करते हैं use @MockBean in different test classes, लेकिन फिर से , स्प्रिंग के पास सभी परीक्षणों के लिए अपने आवेदन के संदर्भ का पुन: उपयोग करने का कोई तरीका नहीं है।

समाधान है to move all @MockBean into an common abstract classऔर यह समस्या को ठीक करता है।

@SpringBootTests(webEnvironment = WebEnvironment.RANDOM_PORT, classes = Application.class)
public abstract class AbstractIT {

   @MockBean
   private ProductService productService;

   @MockBean
   private InvoiceService invoiceService;

}

फिर नीचे परीक्षण कक्षाएं देखी जा सकती हैं

public class ProductControllerIT extends AbstractIT {
   // please don't use @MockBean here
   @Test
   public void searchProduct_ShouldSuccess() {
   }

}

public class InvoiceControllerIT extends AbstractIT {
   // please don't use @MockBean here
   @Test
   public void searchInvoice_ShouldSuccess() {
   }

}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.