Ich habe eine Klasse mit ein paar Tests eingerichtet und @Beforemöchte nicht eine Setup-Methode verwenden, die vor allen Tests nur einmal ausgeführt wird. Ist das mit Junit 4.8 möglich?
Obwohl ich @assylias zustimme, dass die Verwendung @BeforeClasseine klassische Lösung ist, ist sie nicht immer bequem. Die mit annotierte Methode @BeforeClassmuss statisch sein. Dies ist für einige Tests, die eine Testfallinstanz benötigen, sehr unpraktisch. Zum Beispiel Spring-basierte Tests, @Autowiredmit denen mit im Spring-Kontext definierten Diensten gearbeitet wird.
In diesem Fall verwende ich persönlich eine reguläre setUp()Methode, die mit @BeforeAnmerkungen versehen ist, und verwalte mein benutzerdefiniertes static(!) booleanFlag:
privatestaticboolean setUpIsDone =false;.....publicvoid setUp(){if(setUpIsDone){return;}// do the setup
setUpIsDone =true;}
Hinzufügen zu Kenny Casons Kommentar, warum es statisch sein muss. Es muss statisch sein, da JUnit für jede @ Test-Methode eine neue Instanz der Testklasse instanziiert. Die Instanzvariable wird für jede Instanz auf den Standardwert (false) zurückgesetzt, wenn sie nicht statisch ist. Weitere Informationen finden Sie unter: martinfowler.com/bliki/JunitNewInstance.html
Dustin.schultz
2
Dies funktioniert nur in dem Fall, in dem sich die setUp()Methode in einer Oberklasse befindet. Sie haben unten eine Antwort veröffentlicht , um dies zu beheben.
Steve Chambers
4
Ich zögere, dies jemandem mit 84.000 Mitarbeitern zu sagen, aber BeforeClass beantwortet die Frage tatsächlich nicht: BeforeClass wird zu Beginn jeder Testklasse ausgeführt. Das OP forderte jedoch eine, die "nur einmal vor allen Tests" ausgeführt wird. Ihre vorgeschlagene Lösung könnte dies tun, aber Sie müssten alle Ihre Testklassen dazu bringen, eine "CommonTest" -Klasse zu erweitern ...
Mike Nagetier
1
@mikerodent, IMHO OP fragte nach allen Tests in seinem Testfall, nicht nach allen Tests insgesamt. Ihr Kommentar ist also weniger relevant. Übrigens, machen Sie sich keine Sorgen, jemandem etwas zu sagen, auch wenn sein Ruf hoch ist. Zumindest mache ich das :). Und mein Ruf war im August 2012 deutlich niedriger, als ich die Frage beantwortete.
AlexR
Funktioniert in meinem Fall nicht. Im Setup initialisierte Variablen werden nach jedem Test zurückgesetzt, daher ist es sinnlos, nur einmal zu initialisieren.
@mikerodent Ich habe die Frage als "alle Tests in der Klasse" verstanden - aber Sie haben Recht, es ist möglicherweise nicht das, was das OP wollte.
Assylias
29
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).
Es hat das gleiche Problem war @BeforeClass, es muss sein static. Die Lösung von IMO @ AlexR ist besser.
Zengr
@zengr stimmt Ihnen eher zu: Wie ich bereits zu AlexR gesagt habe, erfordert seine Lösung, dass alle Testklassen von einer CommonTest-Klasse untergeordnet werden, wenn sie nur einmal ausgeführt werden sollen. Aber es ist so einfach wie es nur sein kann, und meiner Meinung nach sollten Sie wahrscheinlich keine "ausgefallene" Framework-Lösung verwenden, wenn ein einfacher Mechanismus in der Sprache verfügbar ist. Es sei denn, es gibt natürlich einen guten Grund. Auch die Verwendung einer einfachen Sache wie seiner mit einem guten Typnamen "macht, was auf der Dose steht" hilft bei der Lesbarkeit.
Mike Nagetier
Trotzdem scheint es meiner Meinung nach viel mehr Rechtfertigung für eine "AfterAll" -Anmerkung zu geben: Es wäre sehr schwierig und erfunden, einen Mechanismus zu entwickeln, um zu erkennen, wann alle Tests durchgeführt wurden. Umgekehrt werden Puristen natürlich wahrscheinlich sagen, dass Sie niemals eine "endgültige Bereinigung" durchführen müssen sollten, dh dass jeder "TearDown" alle Ressourcen in einem makellosen Zustand belassen sollte ... und sie haben wahrscheinlich Recht!
Mike Nagetier
Funktioniert dies mit Maven, wo es mehrere Module mit jeweils ihren Tests gibt?
Mark Boon
@mike rodent, in meinem Fall scheint das Einrichten und Herunterfahren von Testdateien im Dateisystem vor / nach jedem Test zu Deadlocks in den Dateien zu führen. Im Moment bin ich unabhängig zu AlexRs Lösung für die einmalige Einrichtung gekommen. Ich habe zwei statische Flags, bereits eingerichtet und schmutzig. setup () ruft cleanup () auf, wenn anfänglich ein fehlerhafter Zustand erkannt wird oder wenn ein Setup-Fehler zu einem fehlerhaften Zustand führt. Um nach dem Ausführen von Tests aufzuräumen, führe ich sie erneut aus. Chaotisch, überhaupt nicht ideal, nicht in unserem Build-Prozess. Immer noch auf der Suche nach einem besseren Weg (jUnit 4.12).
Rebeccah
9
Wenn setUp()es sich um eine Oberklasse der Testklasse handelt (z. B. AbstractTestBaseunten), kann die akzeptierte Antwort wie folgt geändert werden:
publicabstractclassAbstractTestBase{privatestaticClass<?extendsAbstractTestBase> testClass;.....publicvoid 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.
Mit @BeforeAllMethods/ @AfterAllMethodsannotation können Sie jede Methode in der Testklasse in einem Instanzkontext ausführen, in dem alle injizierten Werte verfügbar sind.
öffentliche Klasse TestCaseExtended erweitert TestCase {private static boolean isInitialized = false; private static TestCaseExtended caseExtended; private int serId; @Override public void setUp () löst eine Ausnahme aus {super.setUp (); if (! isInitialized) {caseExtended = new TestCaseExtended (); caseExtended.loadSaveNewSerId (); caseExtended.emptyTestResultsDirectory (); isInitialized = true; }}
Obi Two
0
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:
In Ihre Basis abstrakte Klasse (ich meine abstrakte Klasse , wo Sie Ihre Treiber in initialisieren setUpDriver () Methode) diesen Teil des Codes:
privatestaticboolean 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
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 benutzerdefiniertesstatic
(!)boolean
Flag:quelle
setUp()
Methode in einer Oberklasse befindet. Sie haben unten eine Antwort veröffentlicht , um dies zu beheben.Sie können die
BeforeClass
Anmerkung verwenden :quelle
TheClassYouWant.class
anstelle Ihres getClass () -Aufrufs verwenden können? Dies ist tatsächlich Java :String.class.getName()
.JUnit 5 hat jetzt eine @ BeforeAll-Annotation:
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).
quelle
@BeforeClass
, es muss seinstatic
. 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: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!quelle
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:
Der ctor wird vor den Tests aufgerufen, da sie nicht statisch sind.
quelle
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.quelle
Meine schmutzige Lösung ist:
Ich verwende es als Basis für alle meine Testfälle.
quelle
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:
quelle
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:
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.
quelle
Verwenden Sie die @ PostConstruct-Methode von Spring, um alle Initialisierungsarbeiten auszuführen. Diese Methode wird ausgeführt, bevor einer der @ Test ausgeführt wird
quelle