it-swarm.com.de

Mehrere RunWith-Anweisungen in jUnit

Ich schreibe Unit Test und möchte JUnitParamsRunner und MockitoJUnitRunner für eine Testklasse verwenden.

Leider funktioniert folgendes nicht:

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

Gibt es eine Möglichkeit, Mockito und JUnitParams in einer Testklasse zu verwenden?

97
Hans-Helge

Dies ist nicht möglich, da Sie laut Spezifikation nicht zweimal dieselbe Anmerkung auf dasselbe mit Anmerkungen versehene Element setzen können.

Also, was ist die Lösung? Die Lösung besteht darin, nur eine @RunWith() mit einem Läufer zu setzen, auf den Sie nicht verzichten können, und die andere durch etwas anderes zu ersetzen. In Ihrem Fall werden Sie vermutlich MockitoJUnitRunner entfernen und programmgesteuert das tun, was es tut.

Tatsächlich läuft das einzige, was es tut:

MockitoAnnotations.initMocks(test);

zu Beginn des Testfalls. Die einfachste Lösung besteht darin, diesen Code in die setUp() -Methode einzufügen:

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

Ich bin mir nicht sicher, aber wahrscheinlich Sie sollten den mehrfachen Aufruf dieser Methode mit flag vermeiden:

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

Eine bessere, wiederverwendbare Lösung kann jedoch mit den Regeln von JUnt implementiert werden.

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

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

Fügen Sie Ihrer Testklasse jetzt einfach die folgende Zeile hinzu:

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

und Sie können diesen Testfall mit jedem beliebigen Läufer ausführen.

97
AlexR

Ab JUnit 4.7 und Mockito 1.10.17 ist diese Funktionalität integriert. Da ist ein org.mockito.junit.MockitoRule Klasse. Sie können es einfach importieren und die Zeile hinzufügen

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

zu Ihrer Testklasse.

54
Erica Kane

Diese Lösung funktioniert für jeden möglichen Läufer, nicht nur für dieses Mockito-Beispiel. Beispielsweise; Ändern Sie für den Frühling einfach die Läuferklassen und fügen Sie die erforderlichen Anmerkungen hinzu.

@RunWith(JUnitParamsRunner.class)
public class DatabaseModelTest {

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

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

DatabaseModelTest wird von JUnit ausgeführt. TestMockitoJUnitRunner hängt davon ab (durch Logik) und es wird inside der main in einer @Test - Methode ausgeführt, während der Aufruf JUnitCore.runClasses(TestMockitoJUnitRunner.class). Diese Methode stellt sicher, dass der Hauptläufer korrekt gestartet wird, bevor der Unterläufer static class TestMockitoJUnitRunner Ausgeführt wird, und implementiert effektiv mehrere geschachtelte @RunWith - Annotationen mit abhängigen Testklassen.

Auch auf https://bekce.github.io/junit-multiple-runwith-dependent-tests

14
bekce

Seit der Veröffentlichung von PowerMock 1.6 ist dies so einfach wie möglich

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

Hier erklärt https://blog.jayway.com/2014/11/29/using-another-junit-runner-with-powermock/

6
lekant

In meinem Fall habe ich versucht, eine Methode in Spring Bean und Mock

MockitoAnnotations.initMocks(test);

funktioniert nicht Stattdessen müssen Sie diese Bean wie folgt definieren, um sie mit der Mock-Methode in Ihrer XML-Datei zu erstellen.

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

und füge diese Bohne mit Autodraht in deine Testklasse wie folgt ein.

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

check out this link https://bekce.github.io/junit-multiple-runwith-dependent-tests/ mit diesem Ansatz habe ich einen @RunWith (Parameterized.class) - Outer Runner - mit @ kombiniert RunWith (MockitoJUnitRunner.class) - innerer Läufer. Das einzige, was ich hinzufügen musste, war, meine Mitgliedsvariablen in der äußeren Klasse/Klasse statisch zu machen, um sie für die innere/verschachtelte Klasse/Klasse zugänglich zu machen. Viel Glück und viel Spaß.

0
Legna