Junit 5 with Spring Boot:何时使用@ExtendWith Spring 或 Mockito?
Junit 5 with Spring Boot: When to use @ExtendWith Spring or Mockito?
我有以下 抽象单元测试 class 我的所有具体单元测试 class 都扩展了:
@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;
}
使用 @ExtendWith(SpringExtension.class)
或 @ExtendWith(MockitoExtension.class)
有什么区别?
我问,因为使用任何一个注释似乎都没有区别,并且都在我的代码中分别工作 - 允许我使用 Junit5。那么为什么两者都有效?
具体测试class:
@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());
}
}
相关Build.gradle部分:
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()
}
什么是 Junit 扩展
Junit 5 扩展的目的是扩展测试classes 或方法
的行为
继续阅读 Junit 5 扩展模型 & @ExtendWith
注释:here
SpringExtension integrates the Spring TestContext Framework into JUnit
5's Jupiter programming model.
public class SpringExtension
extends Object
implements BeforeAllCallback, AfterAllCallback, TestInstancePostProcessor, BeforeEachCallback, AfterEachCallback, BeforeTestExecutionCallback, AfterTestExecutionCallback, ParameterResolver{..}
This extension is the JUnit Jupiter equivalent of our JUnit4
MockitoJUnitRunner
public class MockitoExtension
extends java.lang.Object
implements BeforeEachCallback, AfterEachCallback, ParameterResolver{..}
可以看出,SpringExtension
比 MockitoExtension
实现了更多的扩展。
另外 @SpringBootTest
是用 @ExtendWith(SpringExtension.class)
注释的元数据,这意味着每次你的测试都用 SpringExtension
扩展。
@MockBean
是一个 Spring 测试框架注解,与 @ExtendWith(SpringExtension.class)
一起使用
要观察差异,请尝试以下操作
ExtendWith
仅 MockitoExtension
@ExtendWith(MockitoExtension.class)
class TestServiceTest {
@MockBean
TestService service;
@Test
void test() {
assertNotNull(service); // Test will fail
}
}
ExtendWith
仅 SpringExtension
@ExtendWith(SpringExtension.class)
class TestServiceTest {
@MockBean
TestService service;
@Test
void test() {
assertNotNull(service); // Test succeeds
}
}
ExtendWith
与 SpringExtension
和 MockitoExtension
@ExtendWith(MockitoExtension.class)
@ExtendWith(SpringExtension.class)
class TestServiceTest {
@MockBean
TestService service;
@Test
void test() {
assertNotNull(service); // Test succeeds
}
}
由于 @SpringBootTest
测试的注释 class 如前所述,两者都适用于您的情况。
回答问题:什么时候使用@ExtendWith
Spring或Mockito? ,
当测试需要 Spring 测试上下文(自动装配 bean/使用 @MockBean
)以及 JUnit 5 的 Jupiter 编程模型时使用 @ExtendWith(SpringExtension.class)
。这也将通过 TestExecutionListeners 支持 Mockito 注释。
当测试使用Mockito并且需要JUnit 5的Jupiter编程模型支持时使用@ExtendWith(MockitoExtension.class)
希望这对您有所帮助
何时使用@ExtendWith(SpringExtension.class)或@SpringBootTest?
当您使用集成测试-@SpringBootTest 注释-或任何切片测试-@xxxTest 注释-您不需要@ExtendWith(SpringExtension.class) 注释,因为提到的注释包含它。
如果测试@ConfigurationProperties、@Service、@Component注解class(在切片测试用例中未定义-ref:Spring引导参考文档Testing/Auto-configured/SLICED测试项目-,您可以使用@ExtendWith(SpringExtension.class) 而不是@SpringBootTest.
观察:我希望使用@ExtendWith(SpringExtension.class) 进行的测试比使用@SpringBootTest.When 进行的相同测试更快 我在 Eclipse 中进行了一次测试,我观察到了相反的情况。
我有以下 抽象单元测试 class 我的所有具体单元测试 class 都扩展了:
@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;
}
使用 @ExtendWith(SpringExtension.class)
或 @ExtendWith(MockitoExtension.class)
有什么区别?
我问,因为使用任何一个注释似乎都没有区别,并且都在我的代码中分别工作 - 允许我使用 Junit5。那么为什么两者都有效?
具体测试class:
@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());
}
}
相关Build.gradle部分:
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()
}
什么是 Junit 扩展
Junit 5 扩展的目的是扩展测试classes 或方法
的行为继续阅读 Junit 5 扩展模型 & @ExtendWith
注释:here
SpringExtension integrates the Spring TestContext Framework into JUnit 5's Jupiter programming model.
public class SpringExtension
extends Object
implements BeforeAllCallback, AfterAllCallback, TestInstancePostProcessor, BeforeEachCallback, AfterEachCallback, BeforeTestExecutionCallback, AfterTestExecutionCallback, ParameterResolver{..}
This extension is the JUnit Jupiter equivalent of our JUnit4 MockitoJUnitRunner
public class MockitoExtension
extends java.lang.Object
implements BeforeEachCallback, AfterEachCallback, ParameterResolver{..}
可以看出,SpringExtension
比 MockitoExtension
实现了更多的扩展。
另外 @SpringBootTest
是用 @ExtendWith(SpringExtension.class)
注释的元数据,这意味着每次你的测试都用 SpringExtension
扩展。
@MockBean
是一个 Spring 测试框架注解,与 @ExtendWith(SpringExtension.class)
要观察差异,请尝试以下操作
ExtendWith
仅 MockitoExtension
@ExtendWith(MockitoExtension.class)
class TestServiceTest {
@MockBean
TestService service;
@Test
void test() {
assertNotNull(service); // Test will fail
}
}
ExtendWith
仅 SpringExtension
@ExtendWith(SpringExtension.class)
class TestServiceTest {
@MockBean
TestService service;
@Test
void test() {
assertNotNull(service); // Test succeeds
}
}
ExtendWith
与 SpringExtension
和 MockitoExtension
@ExtendWith(MockitoExtension.class)
@ExtendWith(SpringExtension.class)
class TestServiceTest {
@MockBean
TestService service;
@Test
void test() {
assertNotNull(service); // Test succeeds
}
}
由于 @SpringBootTest
测试的注释 class 如前所述,两者都适用于您的情况。
回答问题:什么时候使用@ExtendWith
Spring或Mockito? ,
当测试需要 Spring 测试上下文(自动装配 bean/使用 @MockBean
)以及 JUnit 5 的 Jupiter 编程模型时使用 @ExtendWith(SpringExtension.class)
。这也将通过 TestExecutionListeners 支持 Mockito 注释。
当测试使用Mockito并且需要JUnit 5的Jupiter编程模型支持时使用@ExtendWith(MockitoExtension.class)
希望这对您有所帮助
何时使用@ExtendWith(SpringExtension.class)或@SpringBootTest?
当您使用集成测试-@SpringBootTest 注释-或任何切片测试-@xxxTest 注释-您不需要@ExtendWith(SpringExtension.class) 注释,因为提到的注释包含它。
如果测试@ConfigurationProperties、@Service、@Component注解class(在切片测试用例中未定义-ref:Spring引导参考文档Testing/Auto-configured/SLICED测试项目-,您可以使用@ExtendWith(SpringExtension.class) 而不是@SpringBootTest.
观察:我希望使用@ExtendWith(SpringExtension.class) 进行的测试比使用@SpringBootTest.When 进行的相同测试更快 我在 Eclipse 中进行了一次测试,我观察到了相反的情况。