如何在具有多个测试的 JUnit 类中为特定测试运行tearDown 类型方法?

发布于 2024-10-18 01:00:42 字数 1103 浏览 4 评论 0原文

我有一个 junit testCase 类,其中包含多个测试方法(根据要求,我们不想为每个测试创建单独的类。)

我想为每个测试方法创建一个 tearDown 类型方法,其中将专门为该测试运行。不适用于所有测试。

我的问题是,在许多测试中我在数据库中插入记录,测试它并在测试后删除它。 但是,如果测试中途失败,则控制不会到达最后,我的虚拟记录不会被删除。

我认为一个类只允许使用一个 tearDown() ,并且这个 tearDown() 不知道我创建或插入了什么对象/记录以及要删除什么! !

我想仅为一个特定测试创建一个 tearDown()@After 方法。对于每个方法,类似于 java 中的 finally{}

例如:

 public class TestDummy extends TestCase {

        public void testSample1(){
                     InsertSomeData1();

         assertFalse(true);
         runTearDown1();
    }

    public void testSample2(){
                     InsertSomeData2();
         assertFalse(true);
                     runTearDown2();

    }

      public void runTearDown1(){
      deleteDummyDatafromTestSample1....
     }

      public void runTearDown2(){
      deleteDummyDatafromTestSample2....
     }

}

这里的控件永远不会转到 runTearDown1()runTearDown2() 并且我没有一个常见的 tearDown() 因为它不知道我插入了哪些数据以及特定于每种方法的数据。

I have a junit testCase class with multiple test methods in it ( As requirement , we don't want to create separate class for each test.)

I wanna create a tearDown type method for EACH test method , which will run specifically for that test. Not for ALL test.

My problem is , in many tests i Insert record in database, test it and delete it after test.
But, If a test fails mid way , control don't reaches till end my dummy record ain't deleting.

I think only ONE tearDown() is allowed for one class, and this tearDown() don't know what object/record i created or inserted and what to delete!!!

I want to create a tearDown() or @After method just for one specific test. Something like finally{} in java for each method.

For Eg:

 public class TestDummy extends TestCase {

        public void testSample1(){
                     InsertSomeData1();

         assertFalse(true);
         runTearDown1();
    }

    public void testSample2(){
                     InsertSomeData2();
         assertFalse(true);
                     runTearDown2();

    }

      public void runTearDown1(){
      deleteDummyDatafromTestSample1....
     }

      public void runTearDown2(){
      deleteDummyDatafromTestSample2....
     }

}

Here control will never go to runTearDown1() or runTearDown2() and I don't a one common tearDown() because it won't know what data I inserted and thats specific to each method.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

浅浅 2024-10-25 01:00:42

看来您的测试依赖于固定的数据库,如果您当前的测试失败,未来的测试也会失败。我建议不要关注这个特定问题(为每个测试运行的特定于测试的tearDown 方法),而是关注你的主要问题 - borken 测试。在测试运行之前,它应该始终使用干净的数据库,并且每个测试都应该如此。现在,您的第一个测试与第二个测试有关系(通过数据库)。

正确的方法是在每次测试之前重新创建数据库,或者至少将其重置为基本状态。在这种情况下,您需要这样的测试:

public class TestDummy {

    // this code runs (once) when this test class is run.
    @BeforeClass
    public void setupDatabase() {
        // code that creates the database schema
    }

    // this code runs after all tests in this class are run.
    @AfterClass
    public void teardownDatabase() {
        // code that deletes your database, leaving no trace whatsoever.
    }

    // This code runs before each test case. Use it to, for example, purge the
    // database and fill it with default data.
    @Before
    public void before() {

    }

    // You can use this method to delete all test data inserted by a test method too.
    @After
    public void after() {

    }

    // now for the tests themselves, we should be able to assume the database will
    // always be in the correct state, independent from the previous or next test cases.
    @Test
    public void TestSample2() {
       insertSomeData();
       assertTrue(someData, isValid());
    }
}

免责声明:JUnit 4 测试(使用注释)可能不是正确的注释,甚至可能不是正确的答案。

It seems your test relies on a fixed database, and future tests will break if your current test breaks. What I'd recommend is not to focus on this particular problem (a test-specific tearDown method that runs for each test), but your main problem - borken tests. Before your test run, it should always work with a clean database, and this should be the case for each test. Right now, your first test has a relationship with the second (through the database).

What the right approach would be is that you recreate your database before each test, or at the very least reset it to a basic state. In this case, you'll want a test like this:

public class TestDummy {

    // this code runs (once) when this test class is run.
    @BeforeClass
    public void setupDatabase() {
        // code that creates the database schema
    }

    // this code runs after all tests in this class are run.
    @AfterClass
    public void teardownDatabase() {
        // code that deletes your database, leaving no trace whatsoever.
    }

    // This code runs before each test case. Use it to, for example, purge the
    // database and fill it with default data.
    @Before
    public void before() {

    }

    // You can use this method to delete all test data inserted by a test method too.
    @After
    public void after() {

    }

    // now for the tests themselves, we should be able to assume the database will
    // always be in the correct state, independent from the previous or next test cases.
    @Test
    public void TestSample2() {
       insertSomeData();
       assertTrue(someData, isValid());
    }
}

Disclaimer: JUnit 4 tests (using annotations), might not be the right annotations, might not even be the right answer(s).

叶落知秋 2024-10-25 01:00:42

你可以有这样的东西:

interface DBTest {
  void setUpDB();
  void test();
  void tearDownDB();
}

class DBTestRunner {
  void runTest(DBTest test) throws Exception {
    test.setUpDB();
    try {
      test.test();
    } finally {
      test.tearDownDB();
    }
  }
}

public void test48() throws Exception {
  new DBTestRunner().runTest(new DBTest() {
    public void setUpDB() {...}
    public void test() {...}
    public void tearDownDB() {...}
  });
}

You could have smth like this:

interface DBTest {
  void setUpDB();
  void test();
  void tearDownDB();
}

class DBTestRunner {
  void runTest(DBTest test) throws Exception {
    test.setUpDB();
    try {
      test.test();
    } finally {
      test.tearDownDB();
    }
  }
}

public void test48() throws Exception {
  new DBTestRunner().runTest(new DBTest() {
    public void setUpDB() {...}
    public void test() {...}
    public void tearDownDB() {...}
  });
}
我ぃ本無心為│何有愛 2024-10-25 01:00:42

@iluxa。 Gr8..你的解决方案是完美的!在一个测试类中,我创建了两个测试 test48 和 test49 (与上面的 testSample1 和 testSample2 代码中所需的相同)和 viola!每个测试方法现在都有自己的setup() 和tearDown。只是这个解决方案看起来有点复杂,因为需要在每个方法中使用 DBTestRunner,但我没有看到任何更好的解决方案。我想 Junit 可能有一些直接的解决方案。就像@After或tearDown()带有一些参数或其他东西。
非常感谢。

@iluxa . Gr8.. Your solution is perfect!!! In one test class i created two tests test48 and test49 (same as required in my code above testSample1 and testSample2) and viola! every test method now gets its own setup() and tearDown. Only this solution looks little complicated as need to use DBTestRunner in each method, but I don't see any better solution. I was thinking Junit may have some direct solution. like @After or tearDown() with some parameter or something.
Tks a lot.

会傲 2024-10-25 01:00:42

使用 MethodRule:

public class MyRule implements MethodRule {

    @Override
    public Statement apply(final Statement base, FrameworkMethod method, Object target) {
        return new Statement() {
            @Override
            public void evaluate() throws Throwable {
                try {
                    base.evaluate();
                } catch (AssertionError e) {
                    doFail();
                } finally {
                    doAnyway();
                }
            }
        };
    }
}

然后在您的测试类中声明它:

public class TestDummy{
   public MethodRule rule = new MyRule();
......
}

Use MethodRule:

public class MyRule implements MethodRule {

    @Override
    public Statement apply(final Statement base, FrameworkMethod method, Object target) {
        return new Statement() {
            @Override
            public void evaluate() throws Throwable {
                try {
                    base.evaluate();
                } catch (AssertionError e) {
                    doFail();
                } finally {
                    doAnyway();
                }
            }
        };
    }
}

Then declare it in your test class:

public class TestDummy{
   public MethodRule rule = new MyRule();
......
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文