如何在Junit3中获得@BeforeClass和@AfterClass等价物?

时间:2011-08-26 17:44:59

标签: java android junit junit4 junit3

我想在用测试夹具替换它之前备份我的应用程序的数据库。由于Android限制,我被迫使用Junit3,我想实现@BeforeClass和@AfterClass的等效行为。

  

更新:现在有一个工具(Junit4Android)可以获得支持   Android上的Junit4。这有点像kludge但应该有用。

为了实现@BeforeClass等价物,我一直在使用静态变量并在第一次运行期间初始化它,但我需要能够在运行所有测试后恢复数据库。我想不出有什么方法可以检测上次测试的运行时间(因为我认为不能保证测试执行的顺序。)

public class MyTest extends ActivityInstrumentationTestCase2<MainActivity> {
    private static boolean firstRun = true;

    @Override
    protected void setUp() {
        if(firstRun) {
            firstRun = false;
            setUpDatabaseFixture();
        }
    }
    ...
}

4 个答案:

答案 0 :(得分:8)

来自junit website

  

在套件中包装setUp和tearDown方法。这是为了   如果你想运行一个YourTestClass测试用例,那就是

public static Test suite() {
    return new TestSetup(new TestSuite(YourTestClass.class)) {

        protected void setUp() throws Exception {
            System.out.println(" Global setUp ");
        }
        protected void tearDown() throws Exception {
            System.out.println(" Global tearDown ");
        }
    };
}
  

如果您只想为所有人运行一个setUp和tearDown   testcase,创建一个套件并将testClass添加到它并传递套件   TestSetup构造函数中的对象。但我认为没有太多用法   为此,它在某种程度上违反了JUnit哲学。

答案 1 :(得分:1)

最近,我也在寻找类似的解决方案。幸运的是,在我的情况下,在最后一次测试运行后JVM退出。所以我能够通过添加一个JVM关闭钩子来实现这一点。

// Restore database after running all tests
Runtime.getRuntime().addShutdownHook(new Thread() {
    public void run() {
        restoreDatabase();
    }
});

希望这会有所帮助。

答案 2 :(得分:1)

这不是(优雅地处理数据,所以你不必担心恢复它) testing with mock objects 是什么意思? Android supports mocking

我问一个问题,因为我从未嘲笑Android。


根据我的经验,以及this blog post,当Android测试进入套件并由 InstrumentationTestRunner - ActivityInstrumentationTestCase2 <运行时/ strong>是 ActivityTestCase 的扩展,它是 InstrumentationTestCase 的扩展 - 它们是使用android.test.suitebuilder.TestGrouping.SORT_BY_FULLY_QUALIFIED_NAME按字母顺序排序的,所以你可以使用一种方法恢复数据库,该方法是测试名称中字母表中的低位,例如:

// underscore is low in the alphabet
public void test___________Restore() { 
    ... 
}

注意:

您必须注意继承的测试,因为它们不会按此顺序运行。解决方案是覆盖所有继承的测试,只需从覆盖中调用super()。这将再次按字母顺序执行所有操作。

示例:

// Reusable class w only one time setup and finish. 
// Abstract so it is not run by itself.
public abstract class Parent extends InstrumentationTestCase {
    @LargeTest
    public void test_001_Setup() { ... }

    @LargeTest
    public void test_____Finish() { ... }
}

/*-----------------------------------------------------------------------------*/

// These will run in order shown due to naming.
// Inherited tests would not run in order shown w/o the use of overrides & supers
public class Child extends Parent {
    @LargeTest
    public void test_001_Setup() { super.test_001_Setup(); }

    @SmallTest
    public void test_002_MainViewIsVisible() { ... }

    ...

    @LargeTest
    public void test_____Finish() { super.test_____Finish(); }
}

答案 3 :(得分:0)

我建议避免这种依赖,你需要知道运行测试的顺序。如果您只需要恢复被setUpDatabaseFixture()替换的真实数据库,那么您的解决方案可能来自于使用RenamingDelegatingContext。无论如何,如果您无法避免知道上次测试的运行时间,您可以使用以下内容:

...

private static final int NUMBER_OF_TESTS = 5; // count your tests here
private static int sTestsRun = 0;

...

protected void tearDown() throws Exception {
    super.tearDown();
    sTestsRun += countTestCases();

    if ( sTestsRun >= NUMBER_OF_TESTS ) {
        android.util.Log.d("tearDow", "*** Last test run ***");
    }
}