J'ai une suite de tests d'intégration. J'ai une IntegrationTestBase
classe pour étendre tous mes tests. Cette classe de base a une méthode @Before
( public void setUp()
) et @After
( public void tearDown()
) pour établir des connexions API et DB. Ce que j'ai fait, c'est simplement remplacer ces deux méthodes dans chaque cas de test et appeler super.setUp()
et super.tearDown()
. Cependant, cela peut causer des problèmes si quelqu'un oublie d'appeler le super ou le met au mauvais endroit et qu'une exception est levée et qu'il oublie d'appeler super finalement ou quelque chose comme ça.
Ce que je veux faire, c'est créer les méthodes setUp
and tearDown
sur la classe de base final
, puis ajouter simplement nos propres méthodes @Before
and annotées @After
. En faisant quelques tests initiaux, il semble toujours appeler dans cet ordre:
Base @Before
Test @Before
Test
Test @After
Base @After
mais je suis juste un peu inquiet que la commande ne soit pas garantie et qu'elle puisse causer des problèmes. J'ai regardé autour de moi et je n'ai rien vu sur le sujet. Est-ce que quelqu'un sait si je peux le faire et si je n'ai aucun problème?
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?* }
}
MyTest
manquant est- il unextends
?Réponses:
Oui, ce comportement est garanti:
@Before
:@After
:la source
@Before
méthodes n'est pas garanti. S'il y a 10@Before
méthodes, chacune d'elles peut être exécutée dans n'importe quel ordre; juste avant toute autre méthode.@Before
et sont -elles@After
exécutées avant chaque autre méthode de classe (une fois par méthode), ou juste avant et après toute la suite de méthodes de classe (une fois par classe)?junit-4.12
.Un gotcha potentiel qui m'a mordu auparavant:
J'aime avoir au plus une
@Before
méthode dans chaque classe de test, car l'ordre d'exécution des@Before
méthodes définies dans une classe n'est pas garanti. En règle générale, j'appellerai une telle méthodesetUpTest()
.Mais, bien que
@Before
documenté commeThe @Before methods of superclasses will be run before those of the current class. No other ordering is defined.
, cela ne s'applique que si chaque méthode marquée avec@Before
a un nom unique dans la hiérarchie des classes.Par exemple, j'avais ce qui suit:
Je m'attendais
AbstractFooTest.setUpTest()
à courir avantFooTest.setUpTest()
, mais seulement j'aiFooTest.setupTest()
été exécuté.AbstractFooTest.setUpTest()
n'a pas été appelé du tout.Le code doit être modifié comme suit pour fonctionner:
la source
@Before
ou les@After
méthodes / dans la classe de basefinal
, ainsi le compilateur se plaindra si vous essayez (accidentellement) de les remplacer dans la sous-classe.@Before
méthodes marquées seront ignorées si une sous-classe a également une@Before
méthode.Je pense que sur la base de la documentation de la
@Before
et@After
la bonne conclusion est de donner aux méthodes des noms uniques. J'utilise le modèle suivant dans mes tests:et
donner en conséquence
Avantage de cette approche: les utilisateurs de la classe AbstractBaseTest ne peuvent pas remplacer les méthodes setUp / tearDown par accident. S'ils le souhaitent, ils doivent connaître le nom exact et peuvent le faire.
Inconvénient (mineur) de cette approche: les utilisateurs ne peuvent pas voir qu'il se passe des choses avant ou après leur configuration / déchirement. Ils ont besoin de savoir que ces éléments sont fournis par la classe abstraite. Mais je suppose que c'est la raison pour laquelle ils utilisent la classe abstraite
la source
Si vous changez les choses, vous pouvez déclarer votre résumé de classe de base et faire en sorte que les descendants déclarent les méthodes setUp et tearDown (sans annotations) qui sont appelées dans les méthodes annotées setUp et tearDown de la classe de base.
la source
Vous pouvez utiliser l'
@BeforeClass
annotation pour vous assurer qu'ellesetup()
est toujours appelée en premier. De même, vous pouvez utiliser l'@AfterClass
annotation pour vous assurer qu'elletearDown()
est toujours appelée en dernier.Ce n'est généralement pas recommandé, mais cela est pris en charge .
Ce n'est pas exactement ce que vous voulez - mais cela gardera essentiellement votre connexion DB ouverte tout le temps que vos tests sont en cours d'exécution, puis la fermera une fois pour toutes à la fin.
la source
setupDB()
et de lescloseDB()
marquer avec@BeforeClass
et@AfterClass
et de remplacer vos méthodes avant / après parsetup()
ettearDown()
@BeforeClass
et@AfterClass
doivent être statiques. Qu'en est-il du cas, lorsque nous voulons utiliser des variables d'instance à l'intérieur de ces méthodes?@BeforeClass
avec Powermock: cela ne fonctionne que pour le premier test. Voir ce numéro: github.com/powermock/powermock/issues/398Ce n'est pas une réponse à la question du slogan, mais c'est une réponse aux problèmes mentionnés dans le corps de la question. Au lieu d'utiliser @Before ou @After, envisagez d'utiliser @ org.junit.Rule car cela vous donne plus de flexibilité. ExternalResource (à partir de 4.7) est la règle qui vous intéressera le plus si vous gérez des connexions. De plus, si vous voulez un ordre d'exécution garanti de vos règles, utilisez une RuleChain (à partir de 4.10). Je crois que tous ces éléments étaient disponibles lorsque cette question a été posée. L'exemple de code ci-dessous est copié à partir des javadocs d'ExternalResource.
la source