Czy są jakieś najlepsze praktyki, aby Junit wykonywał funkcję raz w pliku testowym, a także nie powinien być statyczny?
jak @BeforeClass
na funkcji statycznej?
Oto brzydkie rozwiązanie:
@Before void init(){
if (init.get() == false){
init.set(true);
// do once block
}
}
cóż, to jest coś, czego nie chcę robić i szukam zintegrowanego rozwiązania junit.
Odpowiedzi:
Jeśli nie chcesz konfigurować statycznych inicjatorów do jednorazowej inicjalizacji i nie zależy Ci na używaniu JUnit, spójrz na TestNG. TestNG obsługuje niestatyczną, jednorazową inicjalizację z różnymi opcjami konfiguracji, wszystkie przy użyciu adnotacji.
W TestNG byłoby to równoważne z:
@org.testng.annotations.BeforeClass public void setUpOnce() { // One time initialization. }
Do porzucenia,
@org.testng.annotations.AfterClass public void tearDownOnce() { // One time tear down. }
Dla odpowiednika TestNG JUnit 4's
@Before
and@After
, możesz użyć odpowiednio@BeforeMethod
i@AfterMethod
.źródło
Proste stwierdzenie if wydaje się też działać całkiem nieźle:
@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = {"classpath:test-context.xml"}) public class myTest { public static boolean dbInit = false; @Autowired DbUtils dbUtils; @Before public void setUp(){ if(!dbInit){ dbUtils.dropTables(); dbUtils.createTables(); dbInit = true; } } ...
źródło
@AfterClass
odpowiednik, który zrywa się po zakończeniu wszystkich testów?Najłatwiejszym rozwiązaniem jest użycie pustego konstruktora. Nadal można przesłonić konstruktora w klasie rozszerzonej.
Ale to nie jest optymalne z całym dziedzictwem. Dlatego JUnit 4 używa zamiast tego adnotacji.
Inną opcją jest utworzenie metody pomocniczej w klasie factory / util i pozwolenie tej metodzie wykonać całą pracę.
Jeśli używasz Spring, powinieneś rozważyć użycie
@TestExecutionListeners
adnotacji. Coś takiego jak ten test:@RunWith(SpringJUnit4ClassRunner.class) @TestExecutionListeners({CustomTestExecutionListener.class, DependencyInjectionTestExecutionListener.class}) @ContextConfiguration("test-config.xml") public class DemoTest {
Spring
AbstractTestExecutionListener
zawiera na przykład tę pustą metodę, którą możesz nadpisać:public void beforeTestClass(TestContext testContext) throws Exception { /* no-op */ }
UWAGA: NIE przeoczyć / przegapić
DependencyInjectionTestExecutionListener
podczas dodawania niestandardowegoTestExecutionListeners
. Jeśli to zrobisz, wszystkie autoprzewodniki będąnull
.źródło
beforeTestClass()
wywołane przed czy po zainicjowaniu kontekstu?Z łatwością używaj
@BeforeAllMethods
/@AfterAllMethods
adnotacji, aby uruchamiać metodę w kontekście wystąpienia (niestatycznym), w którym będą dostępne wszystkie wstrzyknięte wartości.Jest do tego specjalna biblioteka testowa:
https://mvnrepository.com/artifact/org.bitbucket.radistao.test/before-after-spring-test-runner/0.1.0
https://bitbucket.org/radistao/before-after-spring-test-runner/
Jedyne ograniczenie: działa tylko w przypadku testów wiosennych .
(Jestem twórcą tej biblioteki testowej)
źródło
Nigdy nie próbowałem, ale może możesz utworzyć konstruktor bez argumentów i wywołać swoją funkcję z tego miejsca?
źródło
W artykule omówiono 2 bardzo ładne rozwiązania tego problemu:
źródło
AKTUALIZACJA: Zobacz komentarz Cherry, aby dowiedzieć się, dlaczego poniższa sugestia jest błędna. (Zostawiam odpowiedź tutaj, zamiast ją usuwać, ponieważ komentarz może dostarczyć innym przydatnych informacji, dlaczego to nie działa).
Inną opcją wartą rozważenia przy użyciu wstrzykiwania zależności (np. Spring) jest@PostConstruct
. To zagwarantuje zakończenie iniekcji zależności, co nie miało miejsca w konstruktorze:@PostConstruct public void init() { // One-time initialization... }
źródło
@Before
i@After
metody zostaną wywołane 6 razy! Więc w tym kontekście@PostConstruct
zachowuje się jak@Before
adnotacja. Możesz to po prostu przetestować: po prostu umieść 2 metody testowe w klasie testowej, dodaj@PostConstruct public void init() {System.out.println("started");}
i zobacz w dziennikach, ile razy jest drukowany.@Test
uruchomienia: „Aby uruchomić metodę, JUnit najpierw tworzy nową instancję klasy, a następnie wywołuje metodę z adnotacjami”.Po prostu użyj
@BeforeClass
:@BeforeClass public static void init() { }
Nie ma sensu
init
być statycznym, ponieważ każdy test jest uruchamiany w oddzielnej instancji. Instancja, na którejinit
jest uruchamiana, nie pasowałaby do instancji żadnego testu.Jedynym powodem, dla którego możesz chcieć, aby nie był statyczny, jest przesłonięcie go w podklasach, ale możesz to również zrobić za pomocą metod statycznych. Po prostu użyj tej samej nazwy, a
init
zostanie wywołana tylko metoda podklasy .źródło