@BeforeClass और उत्तराधिकार - निष्पादन का आदेश


90

मेरे पास एक सार आधार वर्ग है, जिसे मैं अपनी इकाई परीक्षणों के लिए एक आधार के रूप में उपयोग करता हूं (TestNG 5.10)। इस वर्ग में, मैं अपने परीक्षणों के लिए पूरे वातावरण को इनिशियलाइज़ करता हूँ, डेटाबेस मैपिंग आदि की स्थापना करता है। इस अमूर्त वर्ग में @BeforeClassएनोटेशन के साथ एक विधि है जो इनिशियलाइज़ेशन करती है।

अगला, मैं उस वर्ग को विशिष्ट वर्गों के साथ बढ़ाता हूं जिसमें मेरे पास @Testविधियां हैं और @BeforeClassविधियां भी हैं । ये विधियाँ पर्यावरण के वर्ग-विशिष्ट आरंभीकरण को करती हैं (उदाहरण के लिए कुछ अभिलेख डेटाबेस में डालें)।

मैं @BeforeClassएनोटेट विधियों के एक विशिष्ट क्रम को कैसे लागू कर सकता हूं ? मुझे एब्सट्रैक्ट बेस क्लास के लोगों की जरूरत है, जो कि फैली हुई क्लास के लोगों से पहले निष्पादित किए जाएं।

उदाहरण:

abstract class A {
    @BeforeClass
    doInitialization() {...}
}

class B extends A {
    @BeforeClass
    doSpecificInitialization() {...}

    @Test
    doTests() {...}
}

अपेक्षित आदेश:

A.doInitialization
B.doSpecificInitialization
B.doTests

वास्तविक आदेश:

B.doSpecificInitialization // <- crashes, as the base init is missing
(A.doInitialization        // <---not executed
 B.doTests)                // <-/

जवाबों:


50

न रखें @BeforeClassपर abstractवर्ग। प्रत्येक उपवर्ग से इसे बुलाओ।

abstract class A {
    void doInitialization() {}
}

class B extends A {
    @BeforeClass
    void doSpecificInitialization() {
        super.doInitialization();
    }

    @Test
    void doTests() {}
}

TestNG की तरह लगता है @BeforeClass(dependsOnMethods={"doInitialization"})- यह एक कोशिश दे।


9
मूल रूप से यही मैं बचना चाहता था: सुपर (अमूर्त) वर्ग के तरीकों को स्पष्ट रूप से कहने की आवश्यकता नहीं है। विशेष रूप से मेरे पास भी कक्षाएं हैं, जो ए से विरासत में मिली हैं, लेकिन उनके पास खुद का @BeforeClass तरीका नहीं है। मुझे उस उद्देश्य के लिए केवल एक सम्मिलित करना होगा।
डोमिनिक सैंडजा

5
dependsOnMethodsवैकल्पिक हल चाल किया था। हालांकि मैं "सुपरक्लास फर्स्ट" अप्रोच पसंद करूंगा ...
डोमिनिक सैंडजा

1
"DependonesMethod" का उपयोग करने के लिए "doInitialization" को "@Test" के साथ एनोटेट नहीं किया जाना चाहिए? यह एक समस्या है क्योंकि तकनीकी रूप से यह अपने आप में एक परीक्षण नहीं है ...
N3da


108

संपादित करें: उत्तर नीचे JUnit के लिए है , लेकिन मैं इसे यहाँ वैसे भी छोड़ दूंगा, क्योंकि यह मददगार हो सकता है।

JUnit एपीआई के अनुसार : "सुपर क्लास के @BeforeClass तरीके वर्तमान वर्ग से पहले चलाए जाएंगे।"

मैंने इसका परीक्षण किया, और यह मेरे लिए काम करने लगता है।

हालाँकि, जैसा कि @Odys में उल्लेख किया गया है, JUnit के लिए आपको अलग-अलग नाम की दो विधियों की आवश्यकता है, हालांकि ऐसा करने पर परिणाम केवल उपवर्ग विधि के रूप में चलाए जाएंगे क्योंकि अभिभावक छायांकित होंगे।


56
भले ही मूल प्रश्न TestNG के लिए था, मैं JUnit के लिए googling के बाद यहां पहुंचा और आपके उत्तर ने मदद की - धन्यवाद!
टीबॉट

9
JUnit के लिए आपको दो तरीकों को अलग-अलग नाम देने की आवश्यकता है, हालांकि ऐसा करने पर परिणाम केवल उपवर्ग विधि के रूप में होगा क्योंकि माता-पिता को छायांकित किया जाएगा।
ओडीस

2
@Odys, इस उल्लेख के लिए बहुत बहुत धन्यवाद। मैं यह पता लगाने के लिए संघर्ष कर रहा था कि मेरे उपवर्ग में "सेटअप" विधि क्यों चल रही है, जबकि इसके सुपरक्लास में कोई भी नहीं था। तुम बस मुझे एक टन की पीड़ा से बचा लिया!
टॉम कैटुलो

आपने मेरा दिन बना दिया। धन्यवाद!
raiks

7

मैंने publicअमूर्त वर्ग और TestNG (6.0.1) से पहले DoInitialization () निष्पादित किया doTestsdoInitialization()यदि मैं publicकक्षा A से हटाता हूं तो TestNG निष्पादित नहीं करता है

public abstract class A {
 @BeforeClass
 doInitialization() {...}
}

class B extends A {    
 @Test
 doTests() {...}
}

1
यह सच है, लेकिन अप्रासंगिक है। यह तब काम नहीं करता है जब कक्षा में एक- नॉटेड विधि B भी होती है @BeforeClass, जैसा कि ओपी के मामले में है।
jpaugh

1
मैने भी वही कीया। ऐसा लगता है कि अगर आधार विधि निजी है तो विरासत का क्रम छूट गया है। धन्यवाद!
मनु

6

मैंने केवल 5.11 के साथ आपके उदाहरण की कोशिश की और मुझे पहले प्राप्त बेस क्लास का @BeforeClass मिला।

क्या आप अपनी testng.xml फ़ाइल पोस्ट कर सकते हैं? हो सकता है कि आप A और B दोनों को वहां निर्दिष्ट कर रहे हों, जबकि केवल B आवश्यक है।

Testng-users मेलिंग-लिस्ट पर बेझिझक फॉलो करें और हम आपकी समस्या पर करीब से नज़र डाल सकते हैं।

- सिडरिक


2
परिभाषित (स्पष्ट रूप से) अंडकोष के लिए कोई .xml नहीं, यह एक्लिप्स और मावेन से चलाया जाता है।
डोमिनिक सैंडजाजा

आप इसे एक्लिप्स से कैसे चला रहे हैं? कक्षा B पर राइट क्लिक करें?
सेड्रिक बीस्ट

4

मैं अभी इसके माध्यम से गया हूँ और इसे प्राप्त करने का एक और तरीका पाया है। बस alwaysRunपर @BeforeClassया @BeforeMethodअमूर्त वर्ग में उपयोग करें , आप अपेक्षा के अनुरूप काम करेंगे।

public class AbstractTestClass {
    @BeforeClass(alwaysRun = true)
    public void generalBeforeClass() {
        // do stuff
        specificBeforeClass();
    }
}

2

जब मैं इससे चलता हूं: JUnitCore.runClasses (TestClass.class); यह माता-पिता को ठीक से निष्पादित करेगा, बच्चे से पहले (आपको सुपर की जरूरत नहीं है ।etUpBeforeClass (); ) यदि आप इसे ग्रहण से चलाते हैं: किसी कारण से यह आधार वर्ग को चलाने में विफल रहता है। आसपास काम: (: आधार वर्ग स्पष्ट रूप कॉल BaseTest.setUpBeforeClass (); ) आप इस मामले में आधार वर्ग में एक ध्वज के लिए चाहते हो सकता है आप किसी अनुप्रयोग से चलाने, अगर यह पहले से ही सेटअप है या नहीं यह निर्धारित करने के। इसलिए यह केवल एक बार चलता है यदि आप इसे दोनों संभावित तरीकों (जैसे कि व्यक्तिगत परीक्षण के लिए ग्रहण से, और ANT के माध्यम से एक बिल्ड रिलीज़ के लिए) के माध्यम से चलाते हैं।

यह ग्रहण के साथ एक बग प्रतीत होता है, या कम से कम अप्रत्याशित परिणाम ..


2

JUnit के लिए : जैसा कि @fortega ने उल्लेख किया है: JUnit एपीआई के अनुसार: "सुपर क्लास के @BeforeClass तरीके वर्तमान वर्ग से पहले चलाए जाएंगे।"

लेकिन एक ही नाम के साथ दोनों तरीकों का नाम न रखने के लिए सावधान रहें । चूंकि इस मामले में अभिभावक विधि बाल अभिभावक द्वारा छिपाई जाएगी। स्रोत


1

कैसे होने के बारे में अपने @BeforeClass विधि को एक विशिष्ट specificBeforeClass () विधि कहते हैं जो उप-वर्गों द्वारा अधिलेखित हो सकती है या नहीं हो सकती है:

public class AbstractTestClass {
  @BeforeClass
  public void generalBeforeClass() {
    // do stuff
    specificBeforeClass();
  }

  protected void specificBeforeClass() {}
}

public class SpecificTest {
  @Override
  protected void specificBeforeClass() {
    // Do specific stuff
  }

  // Tests
}

3
इससे पहले कि आप स्थिर हों ऐसा नहीं हो सकता है, तो आप
क्लिंट के

1

dependsOnMethod इस्तेमाल किया जा सकता है।

वसंत के मामले में ( AbstractTestNGSpringContextTests)

@BeforeClass(alwaysRun = true, dependsOnMethods = "springTestContextPrepareTestInstance")

1

अपना आयात विवरण देखें। यह होना चाहिए

import org.testng.annotations.BeforeClass;

नहीं

import org.junit.BeforeClass;


1

यह मेरे लिए काम करता है -

abstract class A {
    @BeforeClass
    doInitialization() {...}
}

class B extends A {
    @Override
    @BeforeClass
    doInitialization() { 

       //do class specific init

    }   

    @Test
    doTests() {...}
}

1
यह कोड क्या करता है इसकी संक्षिप्त व्याख्या जोड़ें और मूल प्रश्न का उत्तर दें
Cray

0

आप अपने सुपर क्लास में एब्सट्रैक्ट मेथड doSpecialInit () बनाने की कोशिश क्यों नहीं करते हैं, सुपरक्लास में आपके प्रीकॉलस एनोटेट विधि से कहा जाता है।

तो आपकी श्रेणी के उत्तराधिकारियों को इस विधि को लागू करने के लिए मजबूर किया जाता है।


ईमानदार होने के लिए, तर्क भी पिछले 3 1/2 वर्षों के भीतर बदल सकता है क्योंकि मैंने यह सवाल पूछा था ... ;-) तो हाँ, शायद यह एक विचार था, शायद यह काम नहीं किया - मैं ईमानदारी से नहीं करता याद है।
डोमिनिक सैंडजाजा

0

यहां एक और आसान उपाय है।

मेरी विशेष स्थिति यह है कि मुझे सुपरक्लास में "बिडक्लैक" से पहले उपवर्ग में "बिडक्लैस" से नकली सेवाओं को इंजेक्ट करने की आवश्यकता है।

ऐसा करने के लिए - बस @ClassRuleउपवर्ग में एक का उपयोग करें ।

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

@ClassRule
public static ExternalResource mocksInjector = new ExternalResource() {
    @Override
    protected void before() {
        // inject my mock services here
        // Note: this is executed before the parent class @BeforeClass
    }
};

आशा है कि ये आपकी मदद करेगा। यह "रिवर्स" क्रम में स्थिर सेटअप को प्रभावी ढंग से निष्पादित कर सकता है।


0

मैंने आज एक समान मुद्दे का सामना किया है, एकमात्र अंतर यह था कि बेस क्लास सार नहीं था

यहाँ मेरा मामला है

public class A {
    @BeforeClass
    private void doInitialization() {...}
}

public class B extends A {
    @BeforeClass
    private void doSpecificInitialization() {...}

    @Test
    public void doTests() {...}
}

यह हुआ कि @BeforeClassकक्षा ए की एक विधि को कभी भी निष्पादित नहीं किया गया था।

  • ए। औद्योधिकीकरण () -> यह कभी भी चुपचाप किया गया था
  • B.doSpecificInitialization ()
  • B.doTests ()

गोपनीयता मोडिफ़ायर के साथ खेलते हुए मैंने पाया कि टेस्टगैग विरासत में मिली क्लास से एक एनोटेट विधि का निष्पादन नहीं करेगा, यदि कोई विधि क्लास-इनहेरिटर से दिखाई नहीं देती है@BeforeClass

तो यह काम करेगा:

public class A {
    @BeforeClass
    private void doInitialization() {...}
}

public class B extends A {
    @BeforeClass
    //Here a privacy modifier matters -> please make sure your method is public or protected so it will be visible for ancestors
    protected void doSpecificInitialization() {...}

    @Test
    public void doTests() {...}
}

परिणामस्वरूप निम्नलिखित होता है:

  • A.doInitialization ()
  • B.doSpecificInitialization ()
  • B.doTests ()

-1

मेरे मामले में (JUnit) मेरे पास बेस क्लास और व्युत्पन्न वर्ग में सेटअप () नाम के समान तरीके हैं। इस मामले में केवल व्युत्पन्न वर्ग की विधि को कहा जाता है, और मेरे पास यह बेस क्लास विधि है।


-2

विरासत का उपयोग करके इसे प्राप्त करने का एक बेहतर और साफ-सुथरा तरीका निम्नलिखित हो सकता है -

abstract class A {

    @BeforeClass
    void doInitialization() {}
}

class B extends A {

    @Override
    @BeforeClass
    void doInitialization() {
        super.doInitialization();
    }

    @Test
    void doTests() {}
}

1
यदि आपको पेरेंट क्लास में विधि की आवश्यकता है तो सबसे पहले आपको चाइल्ड क्लास में विधि का नाम पेरेंटस से अलग करने की आवश्यकता है (क्योंकि यदि उनके पास एक ही हस्ताक्षर है तो बहुरूपता कार्रवाई में आती है)। मेरा मानना ​​है कि यह एक क्लीनर तरीका है।
अनातोली स्टेपनिउक
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.