开发者

How to run tearDown type method for a specific test in JUnit class with multiple tests?

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 specifica开发者_C百科lly 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.


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).


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() {...}
  });
}


@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.


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();
......
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜