@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 ]

0 голосов
/ 25 июня 2019

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

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

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

       //do class specific init

    }   

    @Test
    doTests() {...}
}
0 голосов
/ 08 апреля 2019

Я столкнулся с подобной проблемой сегодня, единственное отличие заключалось в том, что базовый класс не был абстрактным

Вот мой случай

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.doSpecificInitialization ()
  • 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.doSpecificInitialization ()
  • B.doTests ()
0 голосов
/ 22 марта 2017

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

Моя конкретная ситуация заключается в том, что мне нужно внедрить фиктивные сервисы из "BeforeClass" в подклассе перед выполнением "BeforeClass" в суперклассе.

Чтобы сделать это - просто используйте @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
    }
};

Надеюсь, это поможет. Это может эффективно выполнить статическую настройку в «обратном» порядке.

0 голосов
/ 23 мая 2016

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

abstract class A {

    @BeforeClass
    void doInitialization() {}
}

class B extends A {

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

    @Test
    void doTests() {}
}
0 голосов
/ 04 сентября 2013

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

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

0 голосов
/ 13 марта 2013

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

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