J'ai mis en place une classe avec quelques tests et plutôt que d'utiliser, @Before
j'aimerais avoir une méthode de configuration qui ne s'exécute qu'une seule fois avant tous les tests. Est-ce possible avec Junit 4.8?
J'ai mis en place une classe avec quelques tests et plutôt que d'utiliser, @Before
j'aimerais avoir une méthode de configuration qui ne s'exécute qu'une seule fois avant tous les tests. Est-ce possible avec Junit 4.8?
Réponses:
Bien que je sois d'accord avec @assylias, l'utilisation @BeforeClass
est une solution classique, ce n'est pas toujours pratique. La méthode annotée avec @BeforeClass
doit être statique. C'est très gênant pour certains tests qui nécessitent une instance de cas de test. Par exemple, des tests basés sur Spring qui @Autowired
fonctionnent avec des services définis dans un contexte de printemps.
Dans ce cas, j'utilise personnellement la setUp()
méthode régulière annotée avec @Before
annotation et gère mon drapeau personnalisé static
(!) boolean
:
private static boolean setUpIsDone = false;
.....
@Before
public void setUp() {
if (setUpIsDone) {
return;
}
// do the setup
setUpIsDone = true;
}
setUp()
méthode est dans une superclasse - ont publié une réponse ci-dessous pour tenter de résoudre ce problème.
Vous pouvez utiliser l' BeforeClass
annotation :
@BeforeClass
public static void setUpClass() {
//executed only once, before the first test
}
TheClassYouWant.class
place de votre appel getClass ()? Ceci est Java réelle: String.class.getName()
.
JUnit 5 a maintenant une annotation @BeforeAll:
Indique que la méthode annotée doit être exécutée avant toutes les méthodes @Test dans la classe ou la hiérarchie de classes actuelle; analogue à @BeforeClass de JUnit 4. Ces méthodes doivent être statiques.
Les annotations de cycle de vie de JUnit 5 semblent avoir enfin bien fait les choses! Vous pouvez deviner quelles annotations disponibles sans même regarder (par exemple @BeforeEach @AfterAll)
@BeforeClass
, il doit l'être static
. La solution IMO @ AlexR est plus agréable.
Lorsqu'il setUp()
est dans une superclasse de la classe de test (par exemple AbstractTestBase
ci-dessous), la réponse acceptée peut être modifiée comme suit:
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();
}
}
Cela devrait fonctionner pour une seule setUp()
méthode non statique mais je suis incapable de produire un équivalent pour tearDown()
sans m'égarer dans un monde de réflexion complexe ... Bounty pointe vers tous ceux qui le peuvent!
Edit: Je viens de découvrir lors du débogage que la classe est également instanciée avant chaque test. Je suppose que l'annotation @BeforeClass est la meilleure ici.
Vous pouvez également configurer sur le constructeur, la classe de test est une classe après tout. Je ne sais pas si c'est une mauvaise pratique car presque toutes les autres méthodes sont annotées, mais cela fonctionne. Vous pouvez créer un constructeur comme ça:
public UT () {
// initialize once here
}
@Test
// Some test here...
Le ctor sera appelé avant les tests car ils ne sont pas statiques.
Essayez cette solution: https://stackoverflow.com/a/46274919/907576 :
avec @BeforeAllMethods
/ @AfterAllMethods
annotation, vous pouvez exécuter n'importe quelle méthode de la classe Test dans un contexte d'instance, où toutes les valeurs injectées sont disponibles.
Ma sale solution est:
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;
}
}
...
}
Je l'utilise comme base de base pour tous mes testCases.
Si vous ne voulez pas forcer une déclaration d'une variable qui est définie et vérifiée à chaque sous-test, l'ajout de ceci à un SuperTest pourrait faire:
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 ...
}
}
J'ai résolu ce problème comme ceci:
Ajoutez à votre classe abstraite de base (je veux dire la classe abstraite où vous initialisez votre pilote dans méthode setUpDriver () ) cette partie de code:
private static boolean started = false;
static{
if (!started) {
started = true;
try {
setUpDriver(); //method where you initialize your driver
} catch (MalformedURLException e) {
}
}
}
Et maintenant, si vos cours de test étend de base classe abstraite -> setUpDriver () méthode sera exécutée avant la première @Test seulement UNE fois par course.
Utilisez la méthode @PostConstruct de Spring pour effectuer tout le travail d'initialisation et cette méthode s'exécute avant l'exécution de tout @Test