Відповіді:
Хоча я погоджуюся з @assylias, що використовувати @BeforeClass
класичне рішення, це не завжди зручно. Спосіб, в якому зазначається, @BeforeClass
повинен бути статичним. Це дуже незручно для деяких тестів, які потребують прикладу тестового випадку. Наприклад, весняні тести, які використовуються @Autowired
для роботи з сервісами, визначеними у весняному контексті.
У цьому випадку я особисто використовую звичайний 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...
Цито буде викликано перед тестами, оскільки вони не є статичними.
Спробуйте це рішення: https://stackoverflow.com/a/46274919/907576 :
за допомогою @BeforeAllMethods
/ @AfterAllMethods
annotation ви можете виконати будь-який метод у класі 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 лише ОДИН раз на запуск.
Використовуйте метод @PostConstruct Spring для виконання всіх ініціалізаційних робіт, і цей метод запускається до того, як виконується будь-який з @Test