Ответы:
Хотя я согласен с @assylias, что использование @BeforeClass
- классическое решение, оно не всегда удобно. Метод, помеченный значком, @BeforeClass
должен быть статическим. Это очень неудобно для некоторых тестов, которым нужен экземпляр тестового примера. Например, тесты на основе Spring, которые используются @Autowired
для работы со службами, определенными в контексте Spring .
В этом случае я лично использую обычный setUp()
метод, аннотированный @Before
аннотацией, и управляю своим настраиваемым static
(!) boolean
Флагом:
private static boolean setUpIsDone = false;
.....
@Before
public void setUp() {
if (setUpIsDone) {
return;
}
// do the setup
setUpIsDone = true;
}
setUp()
метод находится в суперклассе - ниже был опубликован ответ, пытающийся решить эту проблему.
Вы можете использовать в BeforeClass
аннотации :
@BeforeClass
public static void setUpClass() {
//executed only once, before the first test
}
TheClassYouWant.class
вместо вызова getClass ()? Это актуально Java: String.class.getName()
.
JUnit 5 теперь имеет аннотацию @BeforeAll:
Обозначает, что аннотированный метод должен выполняться перед всеми методами @Test в текущем классе или иерархии классов; аналогично @BeforeClass из JUnit 4. Такие методы должны быть статическими.
Аннотации жизненного цикла JUnit 5, похоже, наконец-то все поняли! Вы можете догадаться, какие аннотации доступны, даже не глядя (например, @BeforeEach @AfterAll)
@BeforeClass
, что и должна быть static
. Решение IMO @ AlexR лучше.
Когда он setUp()
находится в суперклассе тестового класса (например, AbstractTestBase
ниже), принятый ответ можно изменить следующим образом:
public abstract class AbstractTestBase {
private static Class<? extends AbstractTestBase> testClass;
.....
public void setUp() {
if (this.getClass().equals(testClass)) {
return;
}
// do the setup - once per concrete test class
.....
testClass = this.getClass();
}
}
Это должно сработать для одного нестатического setUp()
метода, но я не могу создать его эквивалент, tearDown()
не попадая в мир сложных отражений ... Награда указывает всем, кто может!
Изменить: я только что узнал при отладке, что класс также создается перед каждым тестом. Думаю, аннотация @BeforeClass здесь лучше всего.
Вы также можете настроить конструктор, в конце концов , тестовый класс - это класс. Я не уверен, что это плохая практика, потому что почти все другие методы аннотированы, но это работает. Вы можете создать такой конструктор:
public UT () {
// initialize once here
}
@Test
// Some test here...
Ctor будет вызываться перед тестами, потому что они не статичны.
Попробуйте это решение: https://stackoverflow.com/a/46274919/907576 :
с аннотацией @BeforeAllMethods
/ @AfterAllMethods
вы можете выполнить любой метод в классе Test в контексте экземпляра, где доступны все введенные значения.
Мое грязное решение:
public class TestCaseExtended extends TestCase {
private boolean isInitialized = false;
private int serId;
@Override
public void setUp() throws Exception {
super.setUp();
if(!isInitialized) {
loadSaveNewSerId();
emptyTestResultsDirectory();
isInitialized = true;
}
}
...
}
Я использую его как базу для всех своих тестов.
Если вы не хотите принудительно объявлять переменную, которая устанавливается и проверяется в каждом подтесте, тогда добавление этого в SuperTest может сделать:
public abstract class SuperTest {
private static final ConcurrentHashMap<Class, Boolean> INITIALIZED = new ConcurrentHashMap<>();
protected final boolean initialized() {
final boolean[] absent = {false};
INITIALIZED.computeIfAbsent(this.getClass(), (klass)-> {
return absent[0] = true;
});
return !absent[0];
}
}
public class SubTest extends SuperTest {
@Before
public void before() {
if ( super.initialized() ) return;
... magic ...
}
}
Я решил эту проблему так:
Добавьте в свой базовый абстрактный класс (я имею в виду абстрактный класс, в котором вы инициализируете свой драйвер в методе setUpDriver () ) эту часть кода:
private static boolean started = false;
static{
if (!started) {
started = true;
try {
setUpDriver(); //method where you initialize your driver
} catch (MalformedURLException e) {
}
}
}
И теперь, если ваши тестовые классы будут расширяться от базового абстрактного класса -> метод setUpDriver () будет выполняться перед первым @Test только ОДИН раз за запуск.
Используйте метод Spring @PostConstruct для выполнения всей работы по инициализации, и этот метод запускается до выполнения любого из @Test.