web-dev-qa-db-fra.com

Junit avant le cours (non statique)

Existe-t-il des pratiques recommandées pour que Junit exécute une fonction une fois dans un fichier de test, et cela ne doit pas non plus être statique.

comme @BeforeClass sur une fonction non statique?

Voici une solution laide:

@Before void init(){
    if (init.get() == false){
        init.set(true);
        // do once block
    }
}

eh bien c'est quelque chose que je ne veux pas faire, et je cherche une solution intégrée junit.

70
Roman

Si vous ne souhaitez pas configurer d'initialisateurs statiques pour une initialisation unique et que vous ne souhaitez pas utiliser JUnit, consultez TestNG. TestNG prend en charge une initialisation unique non statique avec une variété d’options de configuration, toutes utilisant des annotations. 

Dans TestNG, cela équivaudrait à:

@org.testng.annotations.BeforeClass
public void setUpOnce() {
   // One time initialization.
}

Pour le démontage,

@org.testng.annotations.AfterClass
public void tearDownOnce() {
   // One time tear down.
}

Pour l'équivalent TestNG de @Before et @After de JUnit 4, vous pouvez utiliser @BeforeMethod et @AfterMethod respectivement.

18
Kartik

Utiliser un constructeur vide est la solution la plus simple. Vous pouvez toujours remplacer le constructeur dans la classe étendue.

Mais ce n'est pas optimal avec tout l'héritage. C'est pourquoi JUnit 4 utilise plutôt des annotations. 

Une autre option consiste à créer une méthode d'assistance dans une classe factory/util et à laisser cette méthode effectuer le travail.

Si vous utilisez Spring, vous devriez envisager d'utiliser l'annotation @TestExecutionListeners . Quelque chose comme ce test:

@RunWith(SpringJUnit4ClassRunner.class)
@TestExecutionListeners({CustomTestExecutionListener.class, 
     DependencyInjectionTestExecutionListener.class})
@ContextConfiguration("test-config.xml")
public class DemoTest {

La variable AbstractTestExecutionListener de Spring contient par exemple cette méthode vide que vous pouvez remplacer:

public void beforeTestClass(TestContext testContext) throws Exception {
    /* no-op */
}
33
Espen

Une simple déclaration si semble plutôt bien fonctionner: 

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:test-context.xml"})
public class myTest {

    public static boolean dbInit = false;

    @Autowired
    DbUtils dbUtils;

    @Before
    public void setUp(){

        if(!dbInit){

            dbUtils.dropTables();
            dbUtils.createTables();
            dbInit = true;

        }
    }

 ...
32
Upgradingdave

Utilisez facilement les annotations @BeforeAllMethods@AfterAllMethods pour exécuter une méthode dans le contexte de l'instance (non statique), où toutes les valeurs injectées seront disponibles. 

Il existe une bibliothèque de tests spéciale pour cela:

https://mvnrepository.com/artifact/org.bitbucket.radistao.test/before-after-spring-test-runner/0.1.0

https://bitbucket.org/radistao/before-after-spring-test-runner/

La seule limitation: ne fonctionne que pour les tests _/Spring.

(Je suis le développeur de cette bibliothèque de tests)

5
radistao

Il suffit d'utiliser @BeforeClass:

@BeforeClass
public static void init() {
}

init n'a pas de sens d'être non statique car chaque test est exécuté dans une instance distincte. L'instance Sur laquelle init est exécutée ne correspond à l'instance d'aucun test.

La seule raison pour laquelle vous souhaitez peut-être qu'il soit non statique est de le remplacer dans les sous-classes, mais vous pouvez le faire .__ avec des méthodes statiques également. Utilisez simplement le même nom, et seule la méthode init de la sous-classe sera appelée.

0
fgb

Je n'ai jamais essayé, mais vous pouvez peut-être créer un constructeur sans argument et appeler votre fonction à partir de là?

0
Roman

L'article discute de 2 très bonnes solutions à ce problème: 

  1. Junit "clean" avec Runner personnalisé (en utilisant l'interface mais vous pouvez l'étendre avec une annotation personnalisée, par exemple @BeforeInstance)
  2. Auditeurs de l'exécution du printemps, comme mentionné par Espen auparavant.
0
kedzi

UPDATE: Veuillez consulter le commentaire de Cherry pour expliquer pourquoi la suggestion ci-dessous est erronée. (Je garde la réponse ici plutôt que de le supprimer car le commentaire peut fournir des informations utiles) information aux autres sur les raisons pour lesquelles cela ne fonctionne pas .)


Une autre option à considérer si l’utilisation de l’injection de dépendance (par exemple Spring) est @PostConstruct . Cela garantira que l'injection de dépendance est complète, ce qui ne serait pas le cas chez un constructeur:

_@PostConstruct
public void init() {
    // One-time initialization...
}
_
0
Steve Chambers