জুনিট @ এর আগে / @ পরে ডাকা কী আদেশ হয়?


133

আমার একটি ইন্টিগ্রেশন টেস্ট স্যুট আছে। আমার IntegrationTestBaseসমস্ত পরীক্ষা বাড়ানোর জন্য আমার একটি ক্লাস রয়েছে। এই বেস ক্লাসে এপিআই এবং ডিবি সংযোগ স্থাপনের জন্য একটি @Before( public void setUp()) এবং @After( public void tearDown()) পদ্ধতি রয়েছে। আমি যা করছি তা হ'ল প্রতিটি টেস্টকেস এবং কলিং super.setUp()এবং এ দুটি পদ্ধতিকে ওভাররাইড করা super.tearDown()। তবে এটি সমস্যার কারণ হতে পারে যদি কেউ সুপারটি কল করতে ভুলে যায় বা তাদের ভুল জায়গায় রাখে এবং একটি ব্যতিক্রম ছুঁড়ে দেওয়া হয় এবং তারা শেষ পর্যন্ত বা কোনও কিছুতে সুপার কল করতে ভুলে যায়।

আমি কি কাজ করতে চান করতে হয় setUpএবং tearDownবেস বর্গ উপর পদ্ধতি finalএবং তারপর শুধু আমাদের নিজের সটীক যোগ @Beforeএবং @Afterপদ্ধতি। কিছু প্রাথমিক পরীক্ষা করা এটি সর্বদা এই ক্রমে কল করে বলে মনে হচ্ছে:

Base @Before
Test @Before
Test
Test @After
Base @After

তবে আমি কেবলমাত্র উদ্বিগ্ন যে আদেশটি গ্যারান্টিযুক্ত নয় এবং এটি সমস্যার কারণ হতে পারে। আমি চারদিকে তাকালাম এবং বিষয়টিতে কিছুই দেখিনি। কেউ কি জানেন যে আমি এটি করতে পারি এবং কোনও সমস্যা নেই?

কোড:

public class IntegrationTestBase {

    @Before
    public final void setUp() { *always called 1st?* }

    @After
    public final void tearDown() { *always called last?* }
}


public class MyTest extends IntegrationTestBase {

    @Before
    public final void before() { *always called 2nd?* }

    @Test
    public void test() { *always called 3rd?* }

    @After
    public final void after() { *always called 4th?* }
}

1
হয় MyTestএকটি অনুপস্থিত extends?
আইয়ুব

@ আইয়ুব: আর নয় :)
জোয়েল

উত্তর:


135

হ্যাঁ, এই আচরণের নিশ্চয়তা রয়েছে:

@Before:

সুপার @Beforeক্লাসের পদ্ধতিগুলি বর্তমান বর্গের আগে চালানো হবে, যদি না সেগুলি বর্তমান শ্রেণিতে ওভাররাইড করা হয়। অন্য কোন আদেশ সংজ্ঞায়িত করা হয় না।

@After:

দ্য @After ক্লাসে ঘোষিত পদ্ধতিগুলি বর্তমান শ্রেণীর মধ্যে চালিত হবে, যদি না সেগুলি বর্তমান শ্রেণিতে ওভাররাইড করা হয়।


15
স্পষ্টভাবে, সমস্ত @Beforeপদ্ধতির ক্রম-কার্য-সম্পাদনের গ্যারান্টি নেই। যদি 10 টি @Beforeপদ্ধতি থাকে তবে তাদের প্রত্যেককে যে কোনও ক্রমে কার্যকর করা যেতে পারে; অন্য কোনও পদ্ধতির ঠিক আগে
সোয়াতি

5
সুতরাং কিছুটা অস্পষ্ট ডকুমেন্টেশন উদ্ধৃত করার পরিবর্তে, আপনি নিজের কথায় এটি ব্যাখ্যা করতে পারেন? হয় @Beforeএবং @Afterপদ্ধতি সামনে ছুটে ছুটে প্রত্যেক (প্রতি ক্লাসে একবার) (প্রতি পদ্ধতি একবার) অন্য বর্গ পদ্ধতি, বা শুধু সামনে এবং ক্লাস পদ্ধতি সমগ্র স্যুট পরে?
বিটি

5
জন কিউ সিটিজেনের বিবৃত গুরুত্বপূর্ণ ক্যাপচারটি দেখুন: "এটি কেবল তখনই প্রযোজ্য যখন @ পূর্বের সাথে চিহ্নিত প্রতিটি পদ্ধতি শ্রেণীর শ্রেণিবিন্যাসের একটি স্বতন্ত্র নাম রাখে" মনে রাখা খুব গুরুত্বপূর্ণ!
ব্রুনো বোসোলা

ক্লাসে @ পূর্ব (ডি) পদ্ধতিতে এবং এর সুপার ক্লাসে অন্য পদ্ধতিতে একই পদ্ধতির নাম ব্যবহার করে আমার একটি নাম বিরোধ হয়েছে junit-4.12
স্টিফেন

এই বিধিটি কি কনকর্ডিয়নআরনার @ পূর্বপরিবারের নমুনা পদ্ধতিতে প্রযোজ্য?
অ্যাড্রিয়ান প্রানক

51

একটি সম্ভাব্য গোচা যা আমাকে আগে দংশন করেছে:

আমি @Beforeপ্রতিটি পরীক্ষার ক্লাসে সর্বাধিক একটি পদ্ধতি থাকতে চাই , কারণ @Beforeশ্রেণীর মধ্যে নির্ধারিত পদ্ধতিগুলি চালানোর ক্রম গ্যারান্টিযুক্ত নয়। সাধারণত, আমি যেমন একটি পদ্ধতি কল করবsetUpTest()

তবে, যদিও @Beforeএটি হিসাবে নথিভুক্ত করা হয়েছে The @Before methods of superclasses will be run before those of the current class. No other ordering is defined., এটি কেবল তখনই প্রযোজ্য যখন চিহ্নিত প্রতিটি পদ্ধতির শ্রেণিবৃত্তিতে @Beforeএকটি স্বতন্ত্র নাম রয়েছে।

উদাহরণস্বরূপ, আমার নিম্নলিখিতগুলি ছিল:

public class AbstractFooTest {
  @Before
  public void setUpTest() { 
     ... 
  }
}

public void FooTest extends AbstractFooTest {
  @Before
  public void setUpTest() { 
    ...
  }
}

আমি AbstractFooTest.setUpTest()আগে চালানোর আশা করেছিলাম FooTest.setUpTest(), তবে কেবল FooTest.setupTest()মৃত্যুদন্ড কার্যকর করা হয়েছিল। AbstractFooTest.setUpTest()একেবারেই ডাকা হয়নি।

কোডটি কাজ করতে নিম্নলিখিত পরিবর্তন করতে হবে:

public void FooTest extends AbstractFooTest {
  @Before
  public void setUpTest() {
    super.setUpTest();
    ...
  }
}

কেন কেবল বেস ক্লাসে @ পূর্ব পদ্ধতির নাম পরিবর্তন করবেন না? এটি আপনাকে সমস্ত বাচ্চাদের কাছে সুপার ডাকার হাত থেকে রক্ষা করবে ... যাইহোক একই নামের ইস্যুতে ভাল ধরা
লরেন্স টিয়ার্নি

24
জিনিসগুলি আরও সুরক্ষিত করার জন্য কেবল একটি মন্তব্য: নাম সংঘর্ষ এড়ানোর জন্য আপনি বেস পদ্ধতিতে @Before/ @Afterপদ্ধতি (গুলি) তৈরি করতে পারেন final, তাই আপনি (দুর্ঘটনাক্রমে) সাবক্লাসে ওভাররাইড করার চেষ্টা করলে সংকলক অভিযোগ করবে।
স্টিফান উইঙ্কলার

4
একই নামে চালিত না হওয়ার পিতামাতার পদ্ধতিটি JUnit আচরণের মতো শোনাচ্ছে না। এটি ওওপি-তে বেসিক ওভার-রাইডিং কীভাবে কাজ করে তা দেখে মনে হচ্ছে। প্যারেন্ট পদ্ধতিটি মূলত রান সময়ে বিদ্যমান থাকে না। শিশু এটি সমস্ত উদ্দীপনা এবং উদ্দেশ্যগুলির জন্য প্রতিস্থাপন করে। জাভা এভাবেই কাজ করে।
ব্র্যান্ডন

1
আরেকটি গোছা হ'ল পিতামাতাদের ক্লাসগুলি সর্বজনীন হতে হবে, অন্যথায় @Beforeসাবক্লাসেও যদি কোনও @Beforeপদ্ধতি থাকে তবে তাদের চিহ্নিত পদ্ধতিগুলি উপেক্ষা করা হবে ।
rusins

21

আমি মনে করি ডকুমেন্টের ভিত্তিতে @Beforeএবং @Afterসঠিক উপসংহারটি হল পদ্ধতিগুলিকে অনন্য নাম দেওয়া। আমি আমার পরীক্ষায় নিম্নলিখিত ধরণটি ব্যবহার করি:

public abstract class AbstractBaseTest {

  @Before
  public final void baseSetUp() { // or any other meaningful name
    System.out.println("AbstractBaseTest.setUp");
  }

  @After
  public final void baseTearDown() { // or any other meaningful name
    System.out.println("AbstractBaseTest.tearDown");
  }
}

এবং

public class Test extends AbstractBaseTest {

  @Before
  public void setUp() {
    System.out.println("Test.setUp");
  }

  @After
  public void tearDown() {
    System.out.println("Test.tearDown");
  }

  @Test
  public void test1() throws Exception {
    System.out.println("test1");
  }

  @Test
  public void test2() throws Exception {
    System.out.println("test2");
  }
}

ফল হিসাবে দিতে

AbstractBaseTest.setUp
Test.setUp
test1
Test.tearDown
AbstractBaseTest.tearDown
AbstractBaseTest.setUp
Test.setUp
test2
Test.tearDown
AbstractBaseTest.tearDown

এই পদ্ধতির সুবিধা: অ্যাবস্ট্রাকবেস টেস্ট শ্রেণীর ব্যবহারকারীরা দুর্ঘটনাক্রমে সেটআপ / টিয়ারডাউন পদ্ধতিগুলিকে ওভাররাইড করতে পারে না। যদি তারা চায় তবে তাদের সঠিক নামটি জানতে হবে এবং এটি করতে পারে।

(গৌণ) এই পদ্ধতির অসুবিধা: ব্যবহারকারীরা দেখতে পারবেন না যে তাদের সেটআপ / টিয়ারডাউন এর আগে বা পরে কিছু ঘটছে। তাদের জানতে হবে যে এই জিনিসগুলি বিমূর্ত শ্রেণীর দ্বারা সরবরাহ করা হয়েছে। তবে আমি ধরে নিই যে এ কারণেই তারা বিমূর্ত ক্লাসটি ব্যবহার করে


2
দুর্দান্ত উদাহরণ - যদি আপনার কাছে দুটি @ টেস্ট পদ্ধতি থাকে তবে আরও চিত্রিত হবে, সুতরাং দেখা যায় যে প্রতিটি পরীক্ষার পদ্ধতি সেটআপ এবং টিয়ারডাউন মোড়ানো থাকে
চিহ্নিত করুন

আমি মনে করি এটি ওপি-র সর্বোত্তম উত্তরের ভিত্তি, তবে আপনার নিজের উত্তরটি এককভাবে পূরণ করা উচিত। অন্যরা যে পরামর্শ দিয়েছিল তার বিকল্পগুলিও কি আপনি নিজের উদাহরণকে বাড়িয়ে তুলতে পারেন এবং ব্যাখ্যা করতে পারেন কেন আপনার প্রস্তাবটি উচ্চতর?
ওয়াচর

2

যদি আপনি বিষয়গুলি ঘুরিয়ে দেন তবে আপনি আপনার বেস শ্রেণীর বিমূর্ত ঘোষণা করতে পারেন এবং বংশধররা সেটআপ এবং টিয়ারডাউন পদ্ধতিগুলি ঘোষণা করে (কোনও টিকা ছাড়াই) যা বেস ক্লাসের 'এ্যানোটেটেড সেটআপ এবং টিয়ারডাউন পদ্ধতিতে ডাকা হয়।


1
কোনও খারাপ ধারণা নয়, তবে আমি সেই টেস্টগুলিতে একটি চুক্তি প্রয়োগ করতে চাই না যার নিজস্ব সেটআপ / টিয়ারডাউন প্রয়োজন নেই
জোয়েল

2

সর্বদা প্রথম বলা হয় তা @BeforeClassআশ্বস্ত করতে আপনি টীকাটি ব্যবহার করতে পারেন setup()। একইভাবে, আপনি @AfterClassএ্যানোটেশনটি নিশ্চিত করতে ব্যবহার করতে পারেনtearDown() সর্বদা সর্বশেষ বলা হয় তা ।

এটি সাধারণত প্রস্তাবিত নয়, তবে এটি সমর্থিত

এটি আপনি যা চান ঠিক তা নয় - তবে এটি আপনার ডিবি সংযোগটি আপনার পরীক্ষাগুলির পুরো সময়টি উন্মুক্ত রাখবে এবং তারপরে এটি একবারে এবং শেষ পর্যন্ত বন্ধ করে দেবে।


2
আসলে, যদি আপনি এই কাজ করতে গেলাম, আর এক পদ্ধতি তৈরি বলতে চাই setupDB()এবং closeDB()এবং তাদের সঙ্গে উপলক্ষে @BeforeClassএবং @AfterClassসাথে পদ্ধতি পরে আপনার পূর্বে / প্রতিস্থাপন setup()এবংtearDown()
সোয়াতি

পদ্ধতিগুলি সহ টীকাযুক্ত @BeforeClassএবং @AfterClassস্থির হওয়া দরকার। ক্ষেত্রে কী হবে, যখন আমরা এই পদ্ধতির মধ্যে উদাহরণ ভেরিয়েবল ব্যবহার করতে চাই?
প্রতীক সিংহল

@BeforeClassপাওয়ারমক ব্যবহার করার সময় একটি সতর্কতা : এটি কেবল প্রথম পরীক্ষার জন্য কাজ করে। এই সমস্যাটি দেখুন: github.com/powermock/powermock/issues/398
ডগমার

2

এটি ট্যাগলাইন প্রশ্নের উত্তর নয়, তবে এটি প্রশ্নের শরীরে উল্লিখিত সমস্যাগুলির একটি উত্তর। @ পূর্বে বা @ আফটার ব্যবহার না করে @ org.junit.Rule ব্যবহারের দিকে নজর দিন কারণ এটি আপনাকে আরও নমনীয়তা দেয়। এক্সটার্নাল রিসোর্স (4.7 হিসাবে) আপনি যদি সংযোগগুলি পরিচালনা করছেন তবে আপনি সবচেয়ে বেশি আগ্রহী হবেন এমন নিয়ম। এছাড়াও, আপনি যদি নিজের নিয়মের গ্যারান্টিযুক্ত এক্সিকিউশন অর্ডার চান তবে একটি রুলচেইন (4.10 হিসাবে) ব্যবহার করুন। আমি বিশ্বাস করি যখন এই প্রশ্নটি করা হয়েছিল তখন এগুলি সবই পাওয়া যায় were নীচের কোড উদাহরণটি বহিরাগত উত্সের জাভাদোকগুলি থেকে অনুলিপি করা হয়েছে।

 public static class UsesExternalResource {
  Server myServer= new Server();

  @Rule
  public ExternalResource resource= new ExternalResource() {
      @Override
      protected void before() throws Throwable {
          myServer.connect();
         };

      @Override
      protected void after() {
          myServer.disconnect();
         };
     };

  @Test
  public void testFoo() {
      new Client().run(myServer);
     }
 }
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.