web-dev-qa-db-fra.com

Plusieurs instructions RunWith dans jUnit

J'écris un test unitaire et veux utiliser JUnitParamsRunner et MockitoJUnitRunner pour une classe de test.

Malheureusement, ce qui suit ne fonctionne pas:

@RunWith(MockitoJUnitRunner.class)
@RunWith(JUnitParamsRunner.class)
public class DatabaseModelTest {
  // some tests
}

Existe-t-il un moyen d'utiliser les deux, Mockito et JUnitParams dans une classe de test?

97
Hans-Helge

Vous ne pouvez pas faire cela car, selon les spécifications, vous ne pouvez pas mettre deux fois la même annotation sur le même élément annoté.

Donc, quelle est la solution? La solution consiste à ne mettre qu'un @RunWith() avec un coureur sans lequel vous ne pouvez pas vous en tenir et remplacer l'autre par un autre. Dans votre cas, je suppose que vous retirerez MockitoJUnitRunner et ferez ce qu’il fait par programme.

En fait, la seule chose qu'il fait est de courir:

MockitoAnnotations.initMocks(test);

au début du cas de test. Donc, la solution la plus simple est de mettre ce code dans la méthode setUp():

@Before
public void setUp() {
    MockitoAnnotations.initMocks(this);
}

Je ne suis pas sûr, mais probablement vous devriez éviter plusieurs appels de cette méthode en utilisant flag:

private boolean mockInitialized = false;
@Before
public void setUp() {
    if (!mockInitialized) {
        MockitoAnnotations.initMocks(this);
        mockInitialized = true;  
    }
}

Cependant, une solution réutilisable peut être implémentée avec les règles de JUnt.

public class MockitoRule extends TestWatcher {
    private boolean mockInitialized = false;

    @Override
    protected void starting(Description d) {
        if (!mockInitialized) {
            MockitoAnnotations.initMocks(this);
            mockInitialized = true;  
        }
    }
}

Ajoutez maintenant la ligne suivante à votre classe de test:

@Rule public MockitoRule mockitoRule = MockitoJUnit.rule();

et vous pouvez exécuter ce cas de test avec le coureur de votre choix.

97
AlexR

A partir de JUnit 4.7 et de Mockito 1.10.17, cette fonctionnalité est intégrée; il y a un org.mockito.junit.MockitoRule classe. Vous pouvez simplement l'importer et ajouter la ligne

@Rule public MockitoRule mockitoRule = MockitoJUnit.rule();

à votre classe de test.

54
Erica Kane

Cette solution fonctionne pour tous les coureurs possibles, pas seulement cet exemple mockito. Par exemple; pour Spring, il suffit de changer les classes de coureurs et d'ajouter les annotations nécessaires.

@RunWith(JUnitParamsRunner.class)
public class DatabaseModelTest {

    @Test
    public void subRunner() throws Exception {
        JUnitCore.runClasses(TestMockitoJUnitRunner.class);
    }

    @RunWith(MockitoJUnitRunner.class)
    public static class TestMockitoJUnitRunner {
    }
}

DatabaseModelTest sera exécuté par JUnit. TestMockitoJUnitRunner en dépend (par logique) et il sera exécuté à l'intérieur du principal dans une méthode @Test, pendant l'appel JUnitCore.runClasses(TestMockitoJUnitRunner.class). Cette méthode garantit que le coureur principal est démarré correctement avant que le sous-coureur static class TestMockitoJUnitRunner Ne s'exécute, en implémentant efficacement plusieurs annotations @RunWith Imbriquées avec des classes de test dépendantes.

Aussi sur https://bekce.github.io/junit-multiple-runwith-dependent-tests

14
bekce

Depuis la sortie de PowerMock 1.6, vous pouvez le faire aussi facilement que

@RunWith(PowerMockRunner.class)
@PowerMockRunnerDelegate(JUnitParamsRunner.class)
public class DatabaseModelTest {
  // some tests
}

Expliqué ici https://blog.jayway.com/2014/11/29/using-another-junit-runner-with-powermock/

6
lekant

Dans mon cas, j’essayais de me moquer d’une méthode en fève de printemps et

MockitoAnnotations.initMocks(test);

ne fonctionne pas. Au lieu de cela, vous devez définir ce bean comme construit à l'aide de la méthode mock dans votre fichier XML, comme suit.

...
<bean id="classWantedToBeMocked" class="org.mockito.Mockito" factory-method="mock">
    <constructor-arg value="com.fullpath.ClassWantedToBeMocked" />
</bean>
...

et ajoutez ce haricot avec auto-câblé dans votre classe de test comme suit.

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations="file:springconfig.xml")
public class TestClass {
    ...
    @Autowired
    private ClassWantedToBeMocked classWantedToBeMocked;
    ...
    when(classWantedToBeMocked.methodWantedToBeMocked()).thenReturn(...);
    ...
}
2
Heungwoo

consultez ce lien https://bekce.github.io/junit-multiple-runwith-dependent-tests/ en utilisant cette approche, j'ai combiné un @RunWith (Parameterized.class) - coureur externe - avec @ RunWith (MockitoJUnitRunner.class) - Coureur interne. Le seul Tweak que je devais ajouter était de rendre mes variables membres dans la classe externe/coureur statique afin de les rendre accessibles au coureur/à la classe interne/imbriquée. bonne chance et profiter.

0
Legna