@BeforeClass и наследование - порядок исполнения - PullRequest
82 голосов
/ 25 января 2010

У меня есть абстрактный базовый класс, который я использую в качестве основы для своих модульных тестов (TestNG 5.10). В этом классе я инициализирую всю среду для своих тестов, настраиваю сопоставления базы данных и т. Д. Этот абстрактный класс имеет метод с аннотацией @BeforeClass, который выполняет инициализацию.

Затем я расширяю этот класс специальными классами, в которых у меня есть @Test методы, а также @BeforeClass методы. Эти методы выполняют специфическую для класса инициализацию среды (например, помещают некоторые записи в базу данных).

Как я могу обеспечить определенный порядок аннотированных методов @BeforeClass? Мне нужно, чтобы те из абстрактного базового класса выполнялись раньше, чем из расширяющего класса.

Пример:

abstract class A {
    @BeforeClass
    doInitialization() {...}
}

class B extends A {
    @BeforeClass
    doSpecificInitialization() {...}

    @Test
    doTests() {...}
}

Ожидаемый заказ:

A.doInitialization
B.doSpecificInitialization
B.doTests

Фактический заказ:

B.doSpecificInitialization // <- crashes, as the base init is missing
(A.doInitialization        // <---not executed
 B.doTests)                // <-/

Ответы [ 16 ]

94 голосов
/ 25 января 2010

edit: Ниже приведен ответ для JUnit , но я все равно оставлю его здесь, потому что это может быть полезно.

В соответствии с API JUnit : «Методы @BeforeClass для суперклассов будут выполняться до тех, которые используются текущим классом».

Я проверил это, и, похоже, у меня работает.

Однако, как упоминает @Odys ниже, для JUnit вам нужно иметь два различных метода , названные по-разному , хотя в противном случае будет запущен только метод подкласса, поскольку родитель будет затенен.

39 голосов
/ 25 января 2010

Не помещайте @BeforeClass в класс abstract. Назовите его из каждого подкласса.

abstract class A {
    void doInitialization() {}
}

class B extends A {
    @BeforeClass
    void doSpecificInitialization() {
        super.doInitialization();
    }

    @Test
    void doTests() {}
}

Похоже, TestNG имеет @BeforeClass(dependsOnMethods={"doInitialization"}) - попробуйте.

7 голосов
/ 31 марта 2011

Я добавил public к абстрактному классу, и TestNG (6.0.1) выполнила doInitialization () до doTests. TestNG не выполняет doInitialization(), если я удаляю public из класса А.

public abstract class A {
 @BeforeClass
 doInitialization() {...}
}

class B extends A {    
 @Test
 doTests() {...}
}
6 голосов
/ 26 января 2010

Я только что попробовал ваш пример с 5.11, и я получил @BeforeClass базового класса, вызванного первым.

Можете ли вы опубликовать свой файл testng.xml? Может быть, вы указываете там и A, и B, тогда как необходим только B.

Не стесняйтесь следить за списком рассылки testng-users, и мы можем более внимательно рассмотреть вашу проблему.

- Cedric

3 голосов
/ 04 декабря 2013

Я только что прошел через это и нашел еще один способ добиться этого. Просто используйте alwaysRun на @BeforeClass или @BeforeMethod в абстрактном классе, работает так, как вы ожидаете.

public class AbstractTestClass {
    @BeforeClass(alwaysRun = true)
    public void generalBeforeClass() {
        // do stuff
        specificBeforeClass();
    }
}
2 голосов
/ 04 августа 2016

Для JUnit : Как @fortega упомянул: Согласно API JUnit: «Методы @BeforeClass для суперклассов будут запускаться раньше, чем для текущего класса».

Но будьте осторожны , чтобы не называть оба метода с одинаковым именем . Так как в этом случае родительский метод будет скрыт дочерним родителем. Источник .

2 голосов
/ 18 ноября 2011

Когда я запускаю из: JUnitCore.runClasses (TestClass.class); Он будет правильно выполнять родительский процесс перед дочерним (вам не нужно super.SetUpBeforeClass (); ) Если вы запустите его из Eclipse: По какой-то причине не удается запустить базовый класс. Работа вокруг: Вызвать базовый класс явно: ( BaseTest.setUpBeforeClass (); ) Возможно, вы захотите иметь флаг в базовом классе на случай, если вы запустите его из приложения, чтобы определить, установлен он или нет. Поэтому он запускается только один раз, если вы запускаете его с помощью обоих возможных методов (например, из eclipse для личного тестирования и через ANT для выпуска сборки).

Это похоже на ошибку в Eclipse или, по крайней мере, на неожиданные результаты ..

1 голос
/ 03 февраля 2018

Проверьте ваше заявление на импорт. Должно быть

import org.testng.annotations.BeforeClass;

не

import org.junit.BeforeClass;

1 голос
/ 21 июля 2015

dependsOnMethod можно использовать.

например. в случае весны (AbstractTestNGSpringContextTests)

@BeforeClass(alwaysRun = true, dependsOnMethods = "springTestContextPrepareTestInstance")
1 голос
/ 09 июля 2010

Как насчет того, чтобы ваш метод @BeforeClass вызывал пустой метод specificBeforeClass (), который может или не может быть перезаписан подклассами, например так:

public class AbstractTestClass {
  @BeforeClass
  public void generalBeforeClass() {
    // do stuff
    specificBeforeClass();
  }

  protected void specificBeforeClass() {}
}

public class SpecificTest {
  @Override
  protected void specificBeforeClass() {
    // Do specific stuff
  }

  // Tests
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...