Я создал класс с несколькими тестами и вместо использования @Before
Я хотел бы иметь метод установки, который выполняется только один раз перед всеми тестами. Возможно ли это с Junit 4.8?
Junit - запустить метод настройки один раз
Ответ 1
Хотя я согласен с @assylias, что использование @BeforeClass
является классическим решением, но это не всегда удобно. Метод, аннотированный @BeforeClass
должен быть статическим. Это очень неудобно для некоторых тестов, которые требуют экземпляра контрольного примера. Например, тесты на основе Spring, которые используют @Autowired
для работы со службами, определенными в контексте Spring.
В этом случае я лично использую обычный setUp()
@Before
аннотацией @Before
и управляю своим собственным static
(!) boolean
флагом:
private static boolean setUpIsDone = false;
.....
public void setUp() {
if (setUpIsDone) {
return;
}
// do the setup
setUpIsDone = true;
}
Ответ 2
Вы можете использовать аннотацию BeforeClass
:
@BeforeClass
public static void setUpClass() {
//executed only once, before the first test
}
Ответ 3
JUnit 5 теперь имеет @BeforeAll аннотацию:
Обозначает, что аннотированный метод должен быть выполнен до всех @Test методы в текущей иерархии классов или классов; аналогично JUnit 4s @BeforeClass. Такие методы должны быть статическими.
Аннотации жизненного цикла JUnit 5, похоже, наконец-то поняли! Вы можете угадать, какие аннотации доступны, даже не глядя (например, @BeforeEach @AfterAll)
Ответ 4
Когда setUp()
находится в суперклассе тестового класса, принятый ответ может быть изменен следующим образом:
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()
не отклоняясь в мир сложных отражений... Щедрость указывает любому, кто может!
Ответ 5
Edit: Я только что обнаружил, что при отладке создается экземпляр класса перед каждым тестом. Я предполагаю, что аннотация @BeforeClass является лучшей здесь.
Вы также можете настроить конструктор, класс test -. Я не уверен, что это плохая практика, потому что почти все другие методы аннотированы, но это работает. Вы можете создать такой конструктор:
public UT () {
// initialize once here
}
@Test
// Some test here...
ctor будет вызван перед тестами, потому что они не являются статическими.
Ответ 6
Попробуйте это решение: fooobar.com/questions/81653/...:
с аннотацией @BeforeAllMethods
/@AfterAllMethods
вы можете выполнить любой метод в классе Test в контексте экземпляра, где доступны все введенные значения.
Ответ 7
Мое грязное решение:
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;
}
}
...
}
Я использую его как базовую базу для всех моих тестовых случаев.
Ответ 8
Если вы не хотите принудительно объявлять переменную, которая устанавливается и проверяется в каждом подтесте, то добавление этого в 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 ...
}
}
Ответ 9
Я решил эту проблему так:
Добавьте к своему базовому абстрактному классу (я имею в виду абстрактный класс, где вы инициализируете свой драйвер в методе setUpDriver()) эту часть кода:
private static boolean started = false;
static{
if (!started) {
started = true;
try {
setUpDriver(); //method where you initialize your driver
} catch (MalformedURLException e) {
}
}
}
И теперь, если ваши тестовые классы простираются от базового абстрактного класса → метод setUpDriver() будет выполняться до первого @Test только ОДИН раз за цикл.
Ответ 10
Вы можете использовать JUnit 5, который представил аннотации @BeforeAll и @TestInstance.
Хотя по умолчанию @BeforeAll следует использовать со статическим методом, вы можете заставить его работать с нестатическим методом, используя аннотацию @TestInstance, которая может изменить жизненный цикл на класс, а не на этот метод.
Вот фрагмент:
@TestInstance(value = TestInstance.Lifecycle.PER_CLASS)
public class ExampleTest {
@Autowired
private MyRepository myRepository;
@BeforeAll
public void setUp() {
//use injected beans here
}
Согласно документации:
/** * При использовании этого режима новый экземпляр теста будет создаваться один раз для каждого класса теста. * * @see #PER_METHOD */PER_CLASS
Следовательно, класс будет создан один раз, и не будет необходимости использовать статический метод.