У меня есть абстрактный базовый класс, который я использую в качестве основы для своих модульных тестов (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) // <-/
источник
dependsOnMethods
Обходной путь сделал трюк. Хотя я бы предпочел подход «сначала суперкласс» ...edit: ответ ниже для JUnit , но я все равно оставлю его здесь, потому что он может быть полезен.
Согласно JUnit api : «Методы суперклассов @BeforeClass будут выполняться раньше, чем методы текущего класса».
Я тестировал это, и, похоже, у меня это работает.
Однако, как упоминает @Odys ниже, для JUnit вам нужно, чтобы два метода назывались по-разному, хотя в противном случае будет запущен только метод подкласса, потому что родительский элемент будет затенен.
источник
Я добавил
public
в абстрактный класс, и TestNG (6.0.1) выполнил doInitialization () раньшеdoTests
. TestNG не выполняется,doInitialization()
если я удалю егоpublic
из класса A.public abstract class A { @BeforeClass doInitialization() {...} } class B extends A { @Test doTests() {...} }
источник
B
также имеет@BeforeClass
аннотированный метод, как в случае OP.Я только что попробовал ваш пример с 5.11, и сначала я вызываю @BeforeClass базового класса.
Вы можете опубликовать свой файл testng.xml? Возможно, вы указываете там как A, так и B, а необходим только B.
Не стесняйтесь следить за списком рассылки testng-users, и мы сможем более подробно рассмотреть вашу проблему.
- Седрик
источник
Я только что прошел через это и нашел еще один способ добиться этого. Просто используйте
alwaysRun
на@BeforeClass
или@BeforeMethod
в абстрактном классе, работает , как и следовало ожидать.public class AbstractTestClass { @BeforeClass(alwaysRun = true) public void generalBeforeClass() { // do stuff specificBeforeClass(); } }
источник
Когда я бегу из: JUnitCore.runClasses (TestClass.class); Он правильно выполнит родительский элемент перед дочерним (вам не нужен super.SetUpBeforeClass (); ) Если вы запустите его из Eclipse: по какой-то причине он не может запустить базовый класс. Решение проблемы : явным образом вызовите базовый класс: ( BaseTest.setUpBeforeClass (); ) Возможно, вы захотите иметь флаг в базовом классе, если вы запускаете его из приложения, чтобы определить, настроен он уже или нет. Таким образом, он запускается только один раз, если вы запускаете его обоими возможными методами (например, из eclipse для личного тестирования и через ANT для выпуска сборки).
Похоже, это ошибка Eclipse или, по крайней мере, неожиданные результаты.
источник
Для JUnit : Как упомянул @fortega: Согласно JUnit api: «Методы суперклассов @BeforeClass будут выполняться раньше, чем методы текущего класса».
Но будьте осторожны, не называйте оба метода одинаковыми именами . Поскольку в этом случае родительский метод будет скрыт дочерним родителем. Источник .
источник
Как насчет того, чтобы ваш метод @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 }
источник
dependsOnMethod
может быть использован.например, в случае Spring (
AbstractTestNGSpringContextTests
)@BeforeClass(alwaysRun = true, dependsOnMethods = "springTestContextPrepareTestInstance")
источник
Проверьте свой оператор импорта. Должен быть
import org.testng.annotations.BeforeClass;
не
import org.junit.BeforeClass;
источник
Это работает для меня -
abstract class A { @BeforeClass doInitialization() {...} } class B extends A { @Override @BeforeClass doInitialization() { //do class specific init } @Test doTests() {...} }
источник
Почему бы вам не попытаться создать абстрактный метод doSpecialInit () в своем суперклассе, вызываемый из вашего аннотированного метода BeforeClass в суперклассе.
Поэтому разработчики, наследующие ваш класс, вынуждены реализовать этот метод.
источник
Здесь есть еще одно простое решение.
Моя конкретная ситуация заключается в том, что мне нужно внедрить фиктивные службы из «BeforeClass» в подкласс до выполнения «BeforeClass» в суперклассе.
Для этого просто используйте a
@ClassRule
в подклассе.Например:
@ClassRule public static ExternalResource mocksInjector = new ExternalResource() { @Override protected void before() { // inject my mock services here // Note: this is executed before the parent class @BeforeClass } };
Надеюсь, это поможет. Это может эффективно выполнять статическую настройку в «обратном» порядке.
источник
Сегодня я столкнулся с подобной проблемой, единственная разница заключалась в том, что базовый класс не был абстрактным
Вот мой случай
public class A { @BeforeClass private void doInitialization() {...} } public class B extends A { @BeforeClass private void doSpecificInitialization() {...} @Test public void doTests() {...} }
Оказалось, что
@BeforeClass
метод из класса A никогда не выполнялся.Играя с модификаторами секретности я обнаружил , что TestNG не будет выполняться в
@BeforeClass
аннотированный метод из унаследованного класса , если метод не видно из класса-наследодателяИтак, это будет работать:
public class A { @BeforeClass private void doInitialization() {...} } public class B extends A { @BeforeClass //Here a privacy modifier matters -> please make sure your method is public or protected so it will be visible for ancestors protected void doSpecificInitialization() {...} @Test public void doTests() {...} }
В результате происходит следующее:
источник
В моем случае (JUnit) у меня есть те же методы, которые называются setup () в базовом и производном классах. В этом случае вызывается только метод производного класса, и он вызывает метод базового класса.
источник
Лучший и более чистый способ добиться этого с использованием наследования может быть следующим:
abstract class A { @BeforeClass void doInitialization() {} } class B extends A { @Override @BeforeClass void doInitialization() { super.doInitialization(); } @Test void doTests() {} }
источник