运行Android测试setUp()方法会多次调用

6
我正在为我的Android应用创建测试套件,并且拥有如下的setUp方法。
    private static final String TAG_NAME = "TESTING_SUITE";
        public TestingMusicDAO musicDAO;
        public List<Song> songs;
        public Instrumentation instr;
        MusicService musicService;
    @Override
    public void setUp() throws Exception {
        instr = this.getInstrumentation();
        Log.d(TAG_NAME, "Setting up testing songs");
        musicDAO = new TestingMusicDAO(instr.getContext());
        musicService = new MusicServiceImpl(musicDAO);
        musicDAO.getAllSongsFromFile();
        songs = musicDAO.getAllSongs();
        for(Song song : songs)
            Log.d( TAG_NAME, song.toString() );
     }

然后,这些测试是由一个Python工具从文本文件创建的。

public void test1() {
    List<Song> testPlaylist;
    String testArtist = ("The Beatles");
    String actualArtist = ("TheBeatles"); 
    testPlaylist = testingPlaySongsByKeyword(testArtist);
    if(testPlaylist.isEmpty()){
        fail("No Songs Were Found");
    } else {
        for( Song loopsongs : testPlaylist){
            if (!(loopsongs.getArtist().equals(actualArtist))){
                fail("Song Doesnt Contain the artist" + actualArtist + "... Contains ->" + loopsongs.getArtist());
            }
        }
   }
}

每当这些方法之一被调用时,musicDAO 就会被重新生成。我该如何阻止 setup 方法的调用?

3个回答

4
您不需要这么做。JUnit的设计是每个测试只执行一次setUp()tearDown()。如果您想要每个类都执行,可以在构造函数中实现。但请确保不要更改类内部的任何内容。每个测试只执行一次是为了确保所有测试都使用相同的数据开始。

那我需要创建一个测试类的构造函数吗? - Peter Djeneralovic
那是我所知道的唯一只会运行一次的函数。不过最好按照jUnit期望的方式编写测试,这样最终会更少痛苦。 - Gabe Sechan
好的,刚刚生成了每个测试的数据库,但速度非常慢。 - Peter Djeneralovic
1
你可以像Vikash已经提到的那样,使用@BeforeClass@AfterClass,而不是使用构造函数。 - winklerrr
@vikash-kumar-verna的回答是正确的。在JUnit4中,Ctor为每个测试用例执行一次,因为我认为它为每个测试用例创建一个新对象。 - Vilius Sutkus '89

3
你可以使用 JUnit 中的 @BeforeClass@AfterClass 注解。这些注解可以帮助你在测试类中执行一些操作。
@BeforeClass
public static void test_setUp_Once(){
  // Code which you want to be executed only once
  createDb();
}

@AfterClass
public static void test_tearDown_Once(){
  // Code which you want to be executed only once
  deleteDb();
}

注意:您需要将这些方法声明为static才能正常工作。

0

我也遇到了同样的基本问题。我想要测试我的数据库结构,所以我在setUp方法中创建它,在tearDown中删除它。使用构造函数无法解决我需要在所有测试执行完毕后删除数据库的需求,因此我使用了一些可重入逻辑:

static int testsExecutedSoFar = 0;
static boolean isFirstRun = true;

@Override
protected void setUp() throws Exception {
    if(isFirstRun){
        createDb();
        isFirstRun = false;
    }       
}

@Override
protected void tearDown() throws Exception{
    testsExecutedSoFar++;
    if (testsExecutedSoFar == totalNumberOfTestCases())
        deleteDb();     
}

private int totalNumberOfTestCases() {
    return countTestCases()+1; //have to add one for testandroidtestcasesetupproperly added by AndroidTestCase
}

由于JUnit为每次运行创建类的新实例,因此这些字段必须是静态的。魔法数字1必须添加,因为AndroidTestCase将其自己的测试(testandroidtestcasesetupproperly)添加到测试套件中,但它不计入countTestCases()返回的数字。

有点丑陋,但它起了作用。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接