Odpowiedzi:
Chociaż zgadzam się z @assylias, używanie @BeforeClass
jest klasycznym rozwiązaniem nie zawsze jest wygodne. Metoda z adnotacją @BeforeClass
musi być statyczna. Jest to bardzo niewygodne w przypadku niektórych testów, które wymagają wystąpienia przypadku testowego. Na przykład testy oparte na Spring, które służą @Autowired
do pracy z usługami zdefiniowanymi w kontekście Spring.
W tym przypadku osobiście używam zwykłej setUp()
metody z @Before
adnotacją i zarządzam własną flagą static
(!) boolean
:
private static boolean setUpIsDone = false;
.....
@Before
public void setUp() {
if (setUpIsDone) {
return;
}
// do the setup
setUpIsDone = true;
}
setUp()
metoda znajduje się w nadklasie - opublikowali odpowiedź poniżej, próbując rozwiązać ten problem.
Możesz użyć z BeforeClass
adnotacji :
@BeforeClass
public static void setUpClass() {
//executed only once, before the first test
}
TheClassYouWant.class
zamiast wywołania getClass ()? Jest to rzeczywista Java: String.class.getName()
.
JUnit 5 ma teraz adnotację @BeforeAll:
Wskazuje, że metoda z adnotacjami powinna zostać wykonana przed wszystkimi metodami @Test w bieżącej klasie lub hierarchii klas; analogicznie do @BeforeClass w JUnit 4. Takie metody muszą być statyczne.
Wydaje się, że adnotacje dotyczące cyklu życia JUnit 5 w końcu się udało! Możesz odgadnąć, które adnotacje są dostępne, nawet nie patrząc (np. @BeforeEach @AfterAll)
@BeforeClass
, co musi static
. Rozwiązanie IMO @ AlexR jest ładniejsze.
Gdy setUp()
jest w nadklasie klasy testowej (np. AbstractTestBase
Poniżej), zaakceptowaną odpowiedź można zmodyfikować w następujący sposób:
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();
}
}
Powinno to zadziałać w przypadku pojedynczej setUp()
metody niestatycznej , ale nie jestem w stanie stworzyć odpowiednika tearDown()
bez zagłębiania się w świat złożonej refleksji… Nagrody dla każdego, kto może!
Edytować: właśnie dowiedziałem się podczas debugowania, że instancja klasy jest również tworzona przed każdym testem. Myślę, że adnotacja @BeforeClass jest tutaj najlepsza.
Możesz też ustawić na konstruktorze, klasa testowa jest przecież klasą. Nie jestem pewien, czy to zła praktyka, ponieważ prawie wszystkie inne metody są opatrzone adnotacjami, ale działa. Możesz stworzyć takiego konstruktora:
public UT () {
// initialize once here
}
@Test
// Some test here...
Ctor zostanie wywołany przed testami, ponieważ nie są one statyczne.
Wypróbuj to rozwiązanie: https://stackoverflow.com/a/46274919/907576 :
za pomocą @BeforeAllMethods
/ @AfterAllMethods
adnotation można wykonać dowolną metodę w klasie Test w kontekście wystąpienia, w którym dostępne są wszystkie wstrzyknięte wartości.
Moje brudne rozwiązanie to:
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;
}
}
...
}
Używam go jako podstawy do wszystkich moich przypadków testowych.
Jeśli nie chcesz wymuszać deklaracji zmiennej, która jest ustawiana i sprawdzana w każdym podteście, dodanie tego do SuperTestu może zrobić:
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 ...
}
}
Rozwiązałem ten problem w ten sposób:
Dodaj do swojej klasy abstrakcyjnej Base (mam na myśli klasę abstrakcyjną, w której inicjalizujesz sterownik w metodzie setUpDriver () ) tę część kodu:
private static boolean started = false;
static{
if (!started) {
started = true;
try {
setUpDriver(); //method where you initialize your driver
} catch (MalformedURLException e) {
}
}
}
A teraz, jeśli twoje klasy testowe będą rozszerzać się z klasy abstrakcyjnej Base -> metoda setUpDriver () zostanie wykonana przed pierwszym @Test tylko JEDEN raz na uruchomienie.
Użyj metody @PostConstruct Springa, aby wykonać całą pracę inicjalizacyjną, a ta metoda jest uruchamiana przed wykonaniem któregokolwiek z @Test