Antworten:
Obwohl ich @assylias zustimme, dass die Verwendung @BeforeClass
eine klassische Lösung ist, ist sie nicht immer bequem. Die mit annotierte Methode @BeforeClass
muss statisch sein. Dies ist für einige Tests, die eine Testfallinstanz benötigen, sehr unpraktisch. Zum Beispiel Spring-basierte Tests, @Autowired
mit denen mit im Spring-Kontext definierten Diensten gearbeitet wird.
In diesem Fall verwende ich persönlich eine reguläre setUp()
Methode, die mit @Before
Anmerkungen versehen ist, und verwalte mein benutzerdefiniertes static
(!) boolean
Flag:
private static boolean setUpIsDone = false;
.....
public void setUp() {
if (setUpIsDone) {
return;
}
// do the setup
setUpIsDone = true;
}
setUp()
Methode in einer Oberklasse befindet. Sie haben unten eine Antwort veröffentlicht , um dies zu beheben.
Sie können die BeforeClass
Anmerkung verwenden :
@BeforeClass
public static void setUpClass() {
//executed only once, before the first test
}
TheClassYouWant.class
anstelle Ihres getClass () -Aufrufs verwenden können? Dies ist tatsächlich Java : String.class.getName()
.
JUnit 5 hat jetzt eine @ BeforeAll-Annotation:
Gibt an, dass die mit Anmerkungen versehene Methode vor allen @ Test-Methoden in der aktuellen Klasse oder Klassenhierarchie ausgeführt werden soll. analog zu @UeClass von JUnit 4. Solche Methoden müssen statisch sein.
Die Lebenszyklusanmerkungen von JUnit 5 scheinen es endlich richtig gemacht zu haben! Sie können erraten, welche Anmerkungen verfügbar sind, ohne auch nur nachzuschauen (z. B. @BeforeEach @AfterAll).
@BeforeClass
, es muss sein static
. Die Lösung von IMO @ AlexR ist besser.
Wenn setUp()
es sich um eine Oberklasse der Testklasse handelt (z. B. AbstractTestBase
unten), kann die akzeptierte Antwort wie folgt geändert werden:
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();
}
}
Dies sollte für eine einzelne nicht statische setUp()
Methode funktionieren , aber ich kann kein Äquivalent dafür erstellen, tearDown()
ohne in eine Welt komplexer Reflexion zu geraten ... Kopfgeldpunkte für jeden, der es kann!
Bearbeiten: Ich habe gerade beim Debuggen herausgefunden, dass die Klasse auch vor jedem Test instanziiert wird. Ich denke, die @ BeforeClass-Annotation ist hier die beste.
Sie können auch auf dem Konstruktor einrichten, die Testklasse ist schließlich eine Klasse. Ich bin mir nicht sicher, ob es eine schlechte Praxis ist, da fast alle anderen Methoden mit Anmerkungen versehen sind, aber es funktioniert. Sie könnten einen solchen Konstruktor erstellen:
public UT () {
// initialize once here
}
@Test
// Some test here...
Der ctor wird vor den Tests aufgerufen, da sie nicht statisch sind.
Versuchen Sie diese Lösung: https://stackoverflow.com/a/46274919/907576 :
Mit @BeforeAllMethods
/ @AfterAllMethods
annotation können Sie jede Methode in der Testklasse in einem Instanzkontext ausführen, in dem alle injizierten Werte verfügbar sind.
Meine schmutzige Lösung ist:
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;
}
}
...
}
Ich verwende es als Basis für alle meine Testfälle.
Wenn Sie keine Deklaration einer Variablen erzwingen möchten, die für jeden Subtest festgelegt und überprüft wird, können Sie dies einem SuperTest hinzufügen:
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 ...
}
}
Ich habe dieses Problem folgendermaßen gelöst:
In Ihre Basis abstrakte Klasse (ich meine abstrakte Klasse , wo Sie Ihre Treiber in initialisieren setUpDriver () Methode) diesen Teil des Codes:
private static boolean started = false;
static{
if (!started) {
started = true;
try {
setUpDriver(); //method where you initialize your driver
} catch (MalformedURLException e) {
}
}
}
Und jetzt, wenn Ihre Testklassen werden aus erstreckt Basis abstrakter Klasse -> setUpDriver () Methode wird vor dem ersten @Test nur ausgeführt werden , ONE pro Laufzeit.
Verwenden Sie die @ PostConstruct-Methode von Spring, um alle Initialisierungsarbeiten auszuführen. Diese Methode wird ausgeführt, bevor einer der @ Test ausgeführt wird