Ich habe eine Integration Test Suite. Ich habe eine IntegrationTestBase
Klasse für alle meine Tests zu erweitern. Diese Basisklasse verfügt über die Methoden @Before
( public void setUp()
) und @After
( public void tearDown()
) zum Herstellen von API- und DB-Verbindungen. Was ich habe tut zwingende nur diese beiden Methoden in jedem Testfall und ruft super.setUp()
und super.tearDown()
. Dies kann jedoch zu Problemen führen, wenn jemand vergisst, den Super anzurufen, oder ihn an die falsche Stelle setzt und eine Ausnahme ausgelöst wird und er vergisst, den Super im Endlich oder so anzurufen.
Was ich tun möchte, ist, die Methoden setUp
und tearDown
in der Basisklasse zu erstellen final
und dann einfach unsere eigenen Anmerkungen @Before
und @After
Methoden hinzuzufügen . Bei einigen ersten Tests scheint es immer in dieser Reihenfolge aufzurufen:
Base @Before
Test @Before
Test
Test @After
Base @After
aber ich bin nur ein wenig besorgt, dass die Bestellung nicht garantiert ist und dass es Probleme verursachen könnte. Ich habe mich umgesehen und nichts zu diesem Thema gesehen. Weiß jemand, ob ich das kann und keine Probleme habe?
Code:
public class IntegrationTestBase {
@Before
public final void setUp() { *always called 1st?* }
@After
public final void tearDown() { *always called last?* }
}
public class MyTest extends IntegrationTestBase {
@Before
public final void before() { *always called 2nd?* }
@Test
public void test() { *always called 3rd?* }
@After
public final void after() { *always called 4th?* }
}
quelle
MyTest
fehlt einextends
?Antworten:
Ja, dieses Verhalten ist garantiert:
@Before
::@After
::quelle
@Before
Methoden nicht garantiert. Wenn es 10@Before
Methoden gibt, kann jede in beliebiger Reihenfolge ausgeführt werden. kurz vor jeder anderen Methode.@Before
und@After
Methoden vor jeder anderen Klassenmethode (einmal pro Methode) oder kurz vor und nach der gesamten Suite von Klassenmethoden (einmal pro Klasse) ausgeführt?junit-4.12
.Ein möglicher Fall, der mich schon einmal gebissen hat:
Ich möchte höchstens eine
@Before
Methode in jeder Testklasse haben, da die Reihenfolge der Ausführung der@Before
in einer Klasse definierten Methoden nicht garantiert ist. Normalerweise werde ich eine solche Methode aufrufensetUpTest()
.Obwohl dies
@Before
als dokumentiert istThe @Before methods of superclasses will be run before those of the current class. No other ordering is defined.
, gilt dies nur, wenn jede mit gekennzeichnete Methode@Before
einen eindeutigen Namen in der Klassenhierarchie hat.Zum Beispiel hatte ich Folgendes:
Ich hatte erwartet
AbstractFooTest.setUpTest()
, vorher zu laufenFooTest.setUpTest()
, wurde aber nurFooTest.setupTest()
ausgeführt.AbstractFooTest.setUpTest()
wurde überhaupt nicht angerufen.Der Code muss wie folgt geändert werden, damit er funktioniert:
quelle
@Before
/@After
-Methode (n) in der Basisklasse erstellenfinal
, sodass sich der Compiler beschwert, wenn Sie (versehentlich) versuchen, sie in der Unterklasse zu überschreiben.@Before
markierten Methoden ignoriert, wenn eine Unterklasse auch eine@Before
Methode hat.Ich denke, basierend auf der Dokumentation der
@Before
und@After
der richtigen Schlussfolgerung ist es, den Methoden eindeutige Namen zu geben. Ich verwende das folgende Muster in meinen Tests:und
als Ergebnis geben
Vorteil dieses Ansatzes: Benutzer der AbstractBaseTest-Klasse können die setUp / tearDown-Methoden nicht versehentlich überschreiben. Wenn sie wollen, müssen sie den genauen Namen kennen und können es tun.
(Kleiner) Nachteil dieses Ansatzes: Benutzer können nicht sehen, dass vor oder nach ihrem SetUp / TearDown etwas passiert. Sie müssen wissen, dass diese Dinge von der abstrakten Klasse bereitgestellt werden. Aber ich nehme an, das ist der Grund, warum sie die abstrakte Klasse verwenden
quelle
Wenn Sie die Dinge umdrehen, können Sie Ihre Basisklasse als abstrakt deklarieren und Nachkommen setUp- und tearDown-Methoden (ohne Anmerkungen) deklarieren lassen, die in den kommentierten setUp- und tearDown-Methoden der Basisklasse aufgerufen werden.
quelle
Sie können
@BeforeClass
Anmerkungen verwenden, um sicherzustellen, dass diesesetup()
immer zuerst aufgerufen werden. Ebenso können Sie@AfterClass
Anmerkungen verwenden, um sicherzustellen, dass diesetearDown()
immer als letzte aufgerufen werden.Dies wird normalerweise nicht empfohlen, aber unterstützt .
Es ist nicht genau das, was Sie wollen - aber es hält Ihre DB-Verbindung im Wesentlichen während der gesamten Laufzeit Ihrer Tests offen und schließt sie am Ende ein für alle Mal.
quelle
setupDB()
undcloseDB()
und markiert sie mit@BeforeClass
und@AfterClass
und den Austausch Ihre vor / nach Methodensetup()
undtearDown()
@BeforeClass
und@AfterClass
statisch sein müssen. Was ist mit dem Fall, wenn wir Instanzvariablen innerhalb dieser Methoden verwenden möchten?@BeforeClass
mit Powermock: Sie funktioniert nur beim ersten Testlauf. Siehe diese Ausgabe: github.com/powermock/powermock/issues/398Dies ist keine Antwort auf die Slogan-Frage, aber eine Antwort auf die im Hauptteil der Frage genannten Probleme. Anstatt @Before oder @After zu verwenden, sollten Sie @ org.junit.Rule verwenden, da dies Ihnen mehr Flexibilität bietet. ExternalResource (ab 4.7) ist die Regel, an der Sie am meisten interessiert sind, wenn Sie Verbindungen verwalten. Wenn Sie eine garantierte Ausführungsreihenfolge Ihrer Regeln wünschen, verwenden Sie eine RuleChain (ab 4.10). Ich glaube, all diese waren verfügbar, als diese Frage gestellt wurde. Das folgende Codebeispiel wird aus den Javadocs von ExternalResource kopiert.
quelle