Junit 5 mit Spring Boot: Wann sollte @ExtendWith Spring oder Mockito verwendet werden?

Lesezeit: 4 Minuten

Ich habe folgendes abstrakte Unit-Test-Klasse dass alle meine konkreten Unit-Test-Klassen erweitern:

@ExtendWith(SpringExtension.class)
//@ExtendWith(MockitoExtension.class)
@SpringBootTest(
    classes = PokerApplication.class,
    webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT
)
public abstract class AbstractUnitTests {

    @MockBean
    public RoundService roundService;

    @MockBean
    public RoundRepository roundRepository;
}

Was ist der Unterschied zwischen verwenden @ExtendWith(SpringExtension.class) oder @ExtendWith(MockitoExtension.class)?

Ich frage, da die Verwendung einer der Anmerkungen keinen Unterschied zu machen scheint und beide in meinem Code funktionieren – sodass ich Junit5 verwenden kann. Warum funktionieren also beide?

Betonprüfklasse:

    @DisplayName("Test RoundService")
    public class RoundsServiceTest extends AbstractUnitTests {

        private static String STUB_USER_ID = "user3";

        // class under test
        @InjectMocks
        RoundService roundService;

        private Round round;

        private ObjectId objectId;

        @BeforeEach //note this replaces the junit 4 @Before
        public void setUp() {

            initMocks(this);
            round = Mocks.round();
            objectId = Mocks.objectId();
        }

        @DisplayName("Test RoundService.getAllRoundsByUserId()")
        @Test
        public void shouldGetRoundsByUserId() {

            // setup
            given(roundRepository.findByUserId(anyString())).willReturn(Collections.singletonList(round));

            // call method under test
            List<Round> rounds = roundService.getRoundsByUserId(STUB_USER_ID);

            // asserts
            assertNotNull(rounds);
            assertEquals(1, rounds.size());
            assertEquals("user3", rounds.get(0).userId());
        }
}

Relevanter Build.gradle-Abschnitt :

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter'
    implementation 'org.springframework.boot:spring-boot-starter-data-mongodb'
    compile group: 'org.springframework.boot', name: 'spring-boot-starter-web', version: '2.2.2.RELEASE'

    compileOnly 'org.projectlombok:lombok'
    annotationProcessor 'org.projectlombok:lombok'

    testImplementation('org.springframework.boot:spring-boot-starter-test') {
        exclude group: 'org.junit.vintage', module: 'junit-vintage-engine'
    }
    implementation 'junit:junit:4.12'
}

test {
    useJUnitPlatform()
}

Benutzeravatar von RG
RG

Was ist eine Junit-Erweiterung?

Der Zweck von Junit 5-Erweiterungen besteht darin, das Verhalten von Testklassen oder -methoden zu erweitern

Quelle

Weiter lesen Junit 5-Erweiterungsmodell & @ExtendWith Anmerkung:Hier

SpringExtension

SpringExtension integriert das Spring TestContext Framework in das Jupiter-Programmiermodell von JUnit 5.

public class SpringExtension
extends Object
implements BeforeAllCallback, AfterAllCallback, TestInstancePostProcessor, BeforeEachCallback, AfterEachCallback, BeforeTestExecutionCallback, AfterTestExecutionCallback, ParameterResolver{..}

MockitoExtension

Diese Erweiterung ist das JUnit Jupiter-Äquivalent zu unserem JUnit4 MockitoJUnitRunner

public class MockitoExtension
extends java.lang.Object
implements BeforeEachCallback, AfterEachCallback, ParameterResolver{..}

Wie man sieht, SpringExtension implementiert viel mehr Erweiterungen als MockitoExtension.

Auch @SpringBootTest ist meta-annotiert mit @ExtendWith(SpringExtension.class) und das bedeutet jedes Mal, wenn Ihre Tests mit verlängert werden SpringExtension.
@MockBean ist eine Spring-Test-Framework-Anmerkung und wird zusammen mit verwendet @ExtendWith(SpringExtension.class)

Um den Unterschied zu beobachten, versuchen Sie Folgendes

ExtendWith nur MockitoExtension

@ExtendWith(MockitoExtension.class)
class TestServiceTest {

    @MockBean
    TestService service;

    @Test
    void test() {
        assertNotNull(service); // Test will fail
    }

}

ExtendWith nur SpringExtension

@ExtendWith(SpringExtension.class)
class TestServiceTest {

    @MockBean
    TestService service;

    @Test
    void test() {
        assertNotNull(service); // Test succeeds
    }

}

ExtendWith mit beiden SpringExtension Und MockitoExtension

@ExtendWith(MockitoExtension.class)
@ExtendWith(SpringExtension.class)
class TestServiceTest {

    @MockBean
    TestService service;

    @Test
    void test() {
        assertNotNull(service); // Test succeeds
    }

}

Beides funktioniert in deinem Fall aufgrund der @SpringBootTest Anmerkung für die Testklasse wie erläutert.

Um die Frage zu beantworten: Wann verwenden @ExtendWith Frühling oder Mockito? ,

Wenn der Test einen Spring-Test-Kontext erfordert (zum automatischen Verdrahten einer Bean / Verwendung von @MockBean ) zusammen mit der Verwendung des Jupiter-Programmiermodells von JUnit 5 @ExtendWith(SpringExtension.class). Dies unterstützt auch Mockito-Anmerkungen über TestExecutionListeners.

Wenn der Test Mockito verwendet und die Unterstützung des Jupiter-Programmiermodells von JUnit 5 benötigt @ExtendWith(MockitoExtension.class)

Hoffe das hilft

  • Sollte die Verwendung von @InjectMocks arbeite in diesem zusammenhang mit junit5? Ich habe es versucht und einen seltsamen Fehler bekommen.

    – Djangofan

    2. März 2021 um 17:58 Uhr

  • @djangofan posten Sie eine SO-Frage mit reproduzierbarem Testfall

    – RG

    3. März 2021 um 2:36 Uhr

  • Wann verwenden @ExtendWith(SpringExtension.class) oder @SpringBootTest?

    – LunaticJape

    23. Juli 2021 um 19:26 Uhr

  • können wir mock up in @ExtendWith(SpringExtension.class) verwenden?

    – NIRAJ KUMAR

    20. Januar 2022 um 9:33 Uhr

  • Sie lesen jemals etwas und denken, Mann, ich wünschte, sie hätten die Dokumente so geschrieben.

    – Streber

    14. Februar 2022 um 13:59 Uhr

Wenn @ExtendWith(SpringExtension.class) oder @SpringBootTest verwenden?

  • Wenn Sie den Integrationstest -@SpringBootTest-Anmerkung- oder einen Slice-Test -@xxxTest-Anmerkungen- verwenden, benötigen Sie keine @ExtendWith(SpringExtension.class)-Anmerkung, da die erwähnten Anmerkungen diese enthalten.

  • Wenn Sie @ConfigurationProperties, @Service, @Component annotierte Klasse testen (nicht in Slice-Testfällen definiert – ref:Spring Boot Reference Document Testing/Auto-configured / SLICED Tests item-), können Sie stattdessen @ExtendWith(SpringExtension.class) verwenden @SpringBootTest.

Beobachtung: Ich erwarte, dass ein Test mit @ExtendWith(SpringExtension.class) schneller ist als der gleiche Test mit @SpringBootTest. Wenn ich einen Test in Eclipse durchführe, habe ich das Gegenteil beobachtet.

  • In unserem Fall verwenden wir @SpringBootTest und übergeben die spezifischen Konfigurationsklassen, die für den Test benötigt werden. Wenn wir stattdessen nur @ExtendWith(SpringExtension.class) verwenden, baut es den gesamten Anwendungskontext auf, was natürlich länger dauert.

    – Kyrstellaine

    15. Dezember 2021 um 22:07 Uhr

Benutzeravatar von Excalibur
Excalibur

Um einige zusätzliche Informationen hinzuzufügen: Ich habe kürzlich auch herausgefunden, dass, wenn Sie verwenden @Mock kommentierte Abhängigkeiten in der Testklasse mit MockitoExtension und Sie versuchen zu verwenden Mockito.when(mockedDependency.methodName()) In @BeforeAll Setup-Methode, dann erhalten Sie eine NullPointer auf deine verspottete Abhängigkeit.

Aber wenn du dich änderst MockitoExtension Zu SpringExtension, es funktioniert gut. Sieht aus wie mit SpringExtension Mocked Beans wird früher initialisiert (before JUnit startet @BeforeAll Methode) genau so, wie es richtig funktionieren sollte.

1449860cookie-checkJunit 5 mit Spring Boot: Wann sollte @ExtendWith Spring oder Mockito verwendet werden?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy