Вопрос

У меня есть абстрактный базовый класс, который я использую в качестве базы для своих модульных тестов (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)                // <-/
Это было полезно?

Решение

Не ставит @BeforeClass на abstract учебный класс. Назовите это из каждого подкласса.

abstract class A {
    void doInitialization() {}
}

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

    @Test
    void doTests() {}
}

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

Другие советы

редактировать: Ответ ниже для Юнит, но я все равно оставлю это здесь, потому что это может быть полезно.

Согласно JUNIT API: «Методы SuperClass @beforclass будут запущены перед теми текущим классом».

Я проверил это, и, кажется, это работает для меня.

Однако, как упоминает @odys ниже, для JUNIT вам нужно иметь Два метода назвали по -разному хотя, как иначе приведет только к запуску только подкласса, потому что родитель будет затенен.

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

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

class B extends A {    
 @Test
 doTests() {...}
}

Я только что попробовал ваш пример с 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.runclases (testclass.class);Он будет выполнять родителя должным образом, перед ребенком (вам не нужно super.setupbeforeClass ();) Если вы запустите его из Eclipse: по какой -то причине он не может запустить базовый класс. Работа: Позвоните в базовый класс явно: (Basetest.setupbeforeClass ();) Вы можете иметь флаг в базовом классе, если вы запустите его из приложения, чтобы определить, уже настроен или нет. Таким образом, он работает только один раз, если вы запускаете его оба возможных метода (например, от Eclipse для личного тестирования и через ANT для выпуска сборки).

Похоже, это ошибка с затмением или, по крайней мере, неожиданные результаты.

Для Юнита: Как упоминал @Fortega: согласно API JUNIT: «Методы суперкладов @beforclass будут запущены перед теми текущим классом».

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

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

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 может быть использован.

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

@BeforeClass(alwaysRun = true, dependsOnMethods = "springTestContextPrepareTestInstance")

Проверьте свой импорт. Так должно быть

import org.testng.annotations.BeforeClass;

нет

import org.junit.BeforeClass;

Почему бы вам не попытаться создать абстрактный метод dospecialinit () в вашем супер классе, называемый из вашего аннотированного метода BeForeClass в SuperClass.

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

Здесь есть еще одно простое решение.

Моя особая ситуация заключается в том, что мне нужно вводить фиктивные услуги из «beforeclass» в подкласс, прежде чем «beforeclass» в Superclass выполняется.

Для этого - просто используйте @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 никогда не был выполнен.

  • A.Doinitialization () -> Это никогда не выполнялось молча
  • B.доспецифичинициализация ()
  • B.dotests ()

Играя с модификаторами конфиденциальности, я обнаружил, что 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() {...}
}

В результате происходит следующее:

  • A.Doinitialization ()
  • B.доспецифичинициализация ()
  • B.dotests ()

Это работает для меня -

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

class B extends A {
    @Override
    @BeforeClass
    doInitialization() { 

       //do class specific init

    }   

    @Test
    doTests() {...}
}

В моем случае (JUNIT) у меня есть те же методы, называемые setup () в базовом классе и полученный класс. В таком случае Только Метод полученного класса называется, и я могу вызвать метод базового класса.

Лучший и более чистый способ достижения этого с использованием наследования может быть связано с следующим -

abstract class A {

    @BeforeClass
    void doInitialization() {}
}

class B extends A {

    @Override
    @BeforeClass
    void doInitialization() {
        super.doInitialization();
    }

    @Test
    void doTests() {}
}
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top