वर्ग से पहले जून (गैर स्थिर)


84

क्या जुनिट को एक परीक्षण फ़ाइल में एक बार निष्पादित करने के लिए कोई सर्वोत्तम अभ्यास है, और यह भी स्थिर नहीं होना चाहिए।

जैसे @BeforeClassगैर स्थिर समारोह पर?

यहाँ एक बदसूरत समाधान है:

@Before void init(){
    if (init.get() == false){
        init.set(true);
        // do once block
    }
}

अच्छी तरह से यह कुछ है जो मैं नहीं करना चाहता, और मैं एक एकीकृत जूनिट समाधान की तलाश में हूं।


खैर, मेरे पास परीक्षण फ़ाइलों और आधार परीक्षण फ़ाइलों का एक बहुत बड़ा पदानुक्रम है, मुझे बाल परीक्षण कक्षाओं में इस कार्रवाई को ओवरराइड करने की संभावना की आवश्यकता है।
रोमन

1
मुझे वही समस्या थी जिसमें केवल कई पैरामीरीज़ेड परीक्षणों में से एक को लॉगिन करना चाहिए।
डॉकस्पार

5
ध्यान दें कि "बदसूरत" समाधान, वह जो सादे JUnit के साथ काम करता है, नीचे परीक्षण फाड़ नहीं लेते हैं।
१२

जवाबों:


22

यदि आप एक समय के लिए स्थैतिक आरंभीकरण स्थापित नहीं करना चाहते हैं और JUnit का उपयोग करने के बारे में विशेष नहीं हैं, तो TestGG पर एक नज़र डालें। TestNG सभी एनोटेशन का उपयोग करते हुए, विभिन्न प्रकार के कॉन्फ़िगरेशन विकल्पों के साथ नॉन-स्टेटिक, वन-टाइम इनिशियलाइज़ेशन का समर्थन करता है।

TestNG में, यह इसके बराबर होगा:

@org.testng.annotations.BeforeClass
public void setUpOnce() {
   // One time initialization.
}

फाड़ने के लिए,

@org.testng.annotations.AfterClass
public void tearDownOnce() {
   // One time tear down.
}

JUnit 4 का TestNG बराबर के लिए @Beforeऔर @After, आप उपयोग कर सकते हैं @BeforeMethodऔर @AfterMethodक्रमशः।


41

एक सरल अगर बयान बहुत अच्छी तरह से काम करने लगता है:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:test-context.xml"})
public class myTest {

    public static boolean dbInit = false;

    @Autowired
    DbUtils dbUtils;

    @Before
    public void setUp(){

        if(!dbInit){

            dbUtils.dropTables();
            dbUtils.createTables();
            dbInit = true;

        }
    }

 ...

1
अच्छा और सरल! लेकिन एक गैर-स्थैतिक @AfterClassसमकक्ष बनाने के लिए बस इसे अपनाने का एक तरीका नहीं देख सकता है जो सभी परीक्षणों के चलने के बाद आंसू बहाता है?
स्टीव चैम्बर्स

1
इस पद्धति के अपडेट के लिए यहां देखें जो उन परीक्षण वर्गों के लिए काम करना चाहिए जो विरासत का उपयोग करते हैं।
स्टीव चैम्बर्स

36

एक खाली कंस्ट्रक्टर का उपयोग करना सबसे आसान उपाय है। आप अभी भी विस्तारित वर्ग में कंस्ट्रक्टर को ओवरराइड कर सकते हैं।

लेकिन यह सभी विरासत के साथ इष्टतम नहीं है। इसलिए JUnit 4 इसके बजाय एनोटेशन का उपयोग करता है।

एक अन्य विकल्प कारखाने / उपयोग वर्ग में एक सहायक विधि बनाना है और उस विधि को कार्य करने देना है।

यदि आप स्प्रिंग का उपयोग कर रहे हैं, तो आपको @TestExecutionListenersएनोटेशन का उपयोग करने पर विचार करना चाहिए । इस परीक्षण की तरह कुछ:

@RunWith(SpringJUnit4ClassRunner.class)
@TestExecutionListeners({CustomTestExecutionListener.class, 
     DependencyInjectionTestExecutionListener.class})
@ContextConfiguration("test-config.xml")
public class DemoTest {

वसंत के AbstractTestExecutionListenerउदाहरण में यह खाली विधि है जिसे आप ओवरराइड कर सकते हैं:

public void beforeTestClass(TestContext testContext) throws Exception {
    /* no-op */
}

नोट:DependencyInjectionTestExecutionListener कस्टम जोड़ते समय अनदेखा / याद न करें TestExecutionListeners। यदि आप करते हैं, तो सभी ऑटोवियर्स होंगे null


+1 इस तकनीक ने DbUnit का उपयोग करने की इच्छा रखते हुए मेरी समस्या का समाधान किया और प्रति कक्षा एक बार केवल डेटासेट लोड किया
ब्रैड

+1 यह सही है ... उन लोगों के लिए जो स्प्रिंग के प्राचीन संस्करण से बंधे नहीं हैं। :(
माइक मिलर

1
क्या इसे beforeTestClass()संदर्भ के पहले या बाद में आरम्भिक कहा जाएगा ?
धुंधली हो जाती है

@ संदर्भ संदर्भ के बाद शुरू हुआ
आनंद

7

उदाहरण संदर्भ (गैर-स्थैतिक) के अंदर एक विधि को चलाने के लिए आसानी से उपयोग करें @BeforeAllMethods/ @AfterAllMethodsएनोटेशन, जहां सभी इंजेक्शन मूल्य उपलब्ध होंगे।

इसके लिए एक विशेष परीक्षण पुस्तकालय है:

https://mvnrepository.com/artifact/org.bitbucket.radistao.test/before-after-spring-test-runner/0.1.0

https://bitbucket.org/radistao/before-after-spring-test-runner/

एकमात्र सीमा: केवल स्प्रिंग परीक्षण के लिए काम करती है ।

(मैं इस परीक्षण पुस्तकालय का डेवलपर हूं)


0

मैंने कभी कोशिश नहीं की है, लेकिन हो सकता है कि आप एक बिना तर्क के रचनाकार बना सकें और आपको वहां से काम कर सकें?


यह काम करेगा, समस्या यह है कि मुझे इस कार्रवाई को उन कक्षाओं में ओवरराइड करने की संभावना की आवश्यकता है जो इस आधार परीक्षण वर्ग का विस्तार करते हैं
रोमन

@ रोमान: ओह, अब मैं देख रहा हूँ। इसे अपनी पोस्ट में जोड़ें, यह टिप्पणी चीजों को बहुत स्पष्ट करती है।
रोमन

कंस्ट्रक्टर को कई बार बुलाया जाएगा क्योंकि परीक्षण के मामले हैं। प्रत्येक परीक्षण विधि के लिए, नई टेस्ट क्लास ऑब्जेक्ट बनाई जाएगी। इसलिए, कंस्ट्रक्टर का उपयोग करना यहां एक समाधान नहीं है
मणिकंता

इसके अलावा यह निर्भरता इंजेक्शन के साथ काम नहीं करेगा जो पहले से निर्मित वस्तु पर निर्भर करता है।
माइक मिलर

0

लेख इस समस्या के 2 बहुत अच्छे समाधानों पर चर्चा करता है:

  1. कस्टम रनर के साथ "क्लीन" जूनट (इंटरफ़ेस का उपयोग करके, लेकिन आप इसे कस्टम एनोटेशन जैसे @BeforeVststage से बढ़ा सकते हैं)
  2. एस्पन द्वारा पहले बताए गए अनुसार वसंत निष्पादन श्रोता।

0

अद्यतन: नीचे दिए गए सुझाव में त्रुटिपूर्णता के लिए कृपया चेरी द्वारा टिप्पणी देखें। (टिप्पणी को हटाने के बजाय यहां जवाब देने के बजाय दूसरों को उपयोगी जानकारी प्रदान करें क्योंकि यह काम क्यों नहीं करता है।)


निर्भरता इंजेक्शन (जैसे स्प्रिंग) का उपयोग करने पर विचार करने लायक एक अन्य विकल्प है @PostConstruct। यह गारंटी देगा कि निर्भरता इंजेक्शन पूरा हो गया है, जो एक निर्माता में मामला नहीं होगा:

@PostConstruct
public void init() {
    // One-time initialization...
}


7
जुनिट परीक्षणों के मामले में बहुत बुरा समाधान। जूनिट हर बार टेस्ट क्लास का उदाहरण बनाता है जब वह टेस्ट पद्धति चलाता है। इसलिए यदि कक्षा में 6 परीक्षण विधियां, एक क्लास कंस्ट्रक्टर, @Beforeऔर @Afterविधियों को 6 बार कहा जाएगा! तो इस संदर्भ में एनोटेशन की @PostConstructतरह व्यवहार करता है @Before। आप बस इसे टेस्ट कर सकते हैं: टेस्ट क्लास में सिर्फ 2 टेस्ट मेथड्स डालें, @PostConstruct public void init() {System.out.println("started");}लॉग्स में जोड़ें और देखें कि यह कितने समय में छपा है।
चेरी

जानकारी के लिए, मैं अभी JUnit डॉक्यूमेंटेशन में आया हूं, जो इस बात की पुष्टि करता है कि JUnit के बारे में ऊपर वर्णित टिप्पणी में प्रत्येक @Testरन के लिए एक उदाहरण बनाया गया है : "विधि को चलाने के लिए, JUnit पहले क्लास का एक नया उदाहरण बनाता है, फिर एनोटेट पद्धति को लागू करता है।"
स्टीव चैम्बर्स

-2

बस उपयोग करें @BeforeClass:

@BeforeClass
public static void init() {
}

यह initगैर-स्थिर होने का कोई मतलब नहीं है क्योंकि प्रत्येक परीक्षण एक अलग उदाहरण में चलाया जाता है। जो इंस्टेंस initचलाया जाता है वह किसी भी टेस्ट के उदाहरण से मेल नहीं खाता।

एकमात्र कारण यह है कि आप इसे गैर-स्थैतिक होना चाहते हैं, इसे उपवर्गों में ओवरराइड करना है, लेकिन आप इसे स्थैतिक के साथ भी कर सकते हैं। बस एक ही नाम का उपयोग करें, और केवल उपवर्ग initविधि कहा जाएगा।


2
यह पूरा प्रश्न गैर-स्थैतिक तरीके से करने की संभावना के बारे में है, जिसकी आपको कक्षा में कुछ उदाहरण-चर की आवश्यकता है।
साइमन फोर्सबर्ग

@SimonForsberg हाँ, और मैं कह रहा हूँ कि सवाल एक XY समस्या है। ऑप ने कहा कि समस्या बाल वर्गों में व्यवहार को नजरअंदाज कर रही है। यदि उदाहरण के लिए उदाहरण चर की जरूरत है, तो मैं कुछ और सुझा सकता हूं।
fgb


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