У меня есть набор интеграционных тестов. У меня есть IntegrationTestBase
класс для расширения всех моих тестов. Этот базовый класс имеет методы @Before
( public void setUp()
) и @After
( public void tearDown()
) для установления соединений API и БД. Я просто переопределяю эти два метода в каждом тестовом примере и вызываю super.setUp()
и super.tearDown()
. Однако это может вызвать проблемы, если кто-то забывает вызвать super или помещает их в неправильное место, и возникает исключение, и они забывают вызвать super в finally или еще что-то.
То , что я хочу сделать , это сделать setUp
и tearDown
методы в базовом классе , final
а затем просто добавить свою собственную аннотированную @Before
и @After
методу. При выполнении некоторых начальных тестов кажется, что он всегда вызывает в следующем порядке:
Base @Before
Test @Before
Test
Test @After
Base @After
но я немного обеспокоен тем, что порядок не гарантирован и может вызвать проблемы. Я огляделась и ничего не нашла по этой теме. Кто-нибудь знает, смогу ли я это сделать и не будет никаких проблем?
Код:
public class IntegrationTestBase {
@Before
public final void setUp() { *always called 1st?* }
@After
public final void tearDown() { *always called last?* }
}
public class MyTest extends IntegrationTestBase {
@Before
public final void before() { *always called 2nd?* }
@Test
public void test() { *always called 3rd?* }
@After
public final void after() { *always called 4th?* }
}
MyTest
отсутствует знакextends
?Ответы:
Да, такое поведение гарантировано:
@Before
:@After
:источник
@Before
методов не гарантируется. Если есть 10@Before
методов, каждый из них может выполняться в любом порядке; непосредственно перед любым другим методом.@Before
и@After
перед каждым другим методом класса (один раз для каждого метода) или непосредственно перед и после всего набора методов класса (один раз для каждого класса)?junit-4.12
.Одна потенциальная проблема, которая укусила меня раньше:
Мне нравится иметь не более одного
@Before
метода в каждом тестовом классе, потому что порядок выполнения@Before
методов, определенных в классе, не гарантируется. Обычно я назову такой методsetUpTest()
.Но, хотя
@Before
это задокументировано какThe @Before methods of superclasses will be run before those of the current class. No other ordering is defined.
, это применимо только в том случае, если каждый метод, отмеченный значком,@Before
имеет уникальное имя в иерархии классов.Например, у меня было следующее:
Раньше я ожидал
AbstractFooTest.setUpTest()
бежатьFooTest.setUpTest()
, но толькоFooTest.setupTest()
был казнен.AbstractFooTest.setUpTest()
вообще не звонили.Для работы код необходимо изменить следующим образом:
источник
@Before
/@After
метод (ы) в базовом классеfinal
, поэтому компилятор будет жаловаться, если вы (случайно) попытаетесь переопределить их в подклассе.@Before
отмеченные методы будут проигнорированы, если у подкласса также есть@Before
метод.Я думаю, что на основе документации
@Before
и@After
правильным выводом будет дать методам уникальные имена. В своих тестах я использую следующий шаблон:и
дать в результате
Преимущество этого подхода: пользователи класса AbstractBaseTest не могут случайно переопределить методы setUp / tearDown. Если они хотят, им нужно знать точное имя и они могут это сделать.
(Незначительный) недостаток этого подхода: пользователи не видят, что что-то происходит до или после их setUp / tearDown. Им нужно знать, что эти вещи предоставляются абстрактным классом. Но я предполагаю, что причина, по которой они используют абстрактный класс
источник
Если вы все измените, вы можете объявить абстрактный базовый класс, а потомки объявить методы setUp и tearDown (без аннотаций), которые вызываются в аннотированных методах setUp и tearDown базового класса.
источник
Вы можете использовать
@BeforeClass
аннотацию, чтобы гарантировать, чтоsetup()
всегда вызывается первым. Точно так же вы можете использовать@AfterClass
аннотацию, чтобы гарантировать, чтоtearDown()
всегда вызывается последней.Обычно это не рекомендуется, но поддерживается .
Это не совсем то, что вы хотите, но по сути это будет держать ваше соединение с БД открытым все время выполнения ваших тестов, а затем закрыть его раз и навсегда в конце.
источник
setupDB()
иcloseDB()
пометить их с помощью@BeforeClass
и@AfterClass
и заменить ваши методы до / после с помощьюsetup()
иtearDown()
@BeforeClass
и@AfterClass
должны быть статическими. А как насчет случая, когда мы хотим использовать переменные экземпляра внутри этих методов?@BeforeClass
с Powermock: работает только при первом тестовом запуске. См. Этот выпуск: github.com/powermock/powermock/issues/398Это не ответ на вопрос с лозунгом, но это ответ на проблемы, упомянутые в теле вопроса. Вместо использования @Before или @After попробуйте использовать @ org.junit.Rule, потому что это дает вам больше гибкости. ExternalResource (начиная с версии 4.7) - это правило, которое вас больше всего заинтересует, если вы управляете соединениями. Кроме того, если вам нужен гарантированный порядок выполнения ваших правил, используйте RuleChain ( начиная с 4.10). Я считаю, что все они были доступны, когда был задан этот вопрос. Пример кода ниже скопирован из javadocs ExternalResource.
источник