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()
}
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
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.
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.