Spring Boot Test单元测试——Junit4、Junit5区别与@ExtendWith不识别生效问题解析

一、SpringBoot2.4.x之后,改为默认仅集成JUnit5,干掉了兼容JUnit4

1. 根本原因

新版本2.4之后的spring-boot-starter-test中去掉了兼容junit4引擎org.junit.vintage:junit-vintage-engine

2. SpringBoot2.4.0之后

spring-boot-starter-test默认仅支持JUnit5

@ExtendWith(SpringExtension.class) // 注意这里
@SpringBootTest
public class Test{
 ...
}

3. SpringBoot2.4.0之前

spring-boot-starter-test默认使用JUnit5,同时兼容支持JUnit4

@RunWith(SpringRunner.class) // 注意这里
@SpringBootTest
public class Test{
 ...
}

4. 特殊说明:

spring-boot-starter-test版本大于2.2小于2.4时,若想只用Junit5,需要excluding org.junit.vintage:junit-vintage-engine,以刨除Junit4的干扰。 

以下是引用stackoverflow中网友回答的原文(java - spring-boot-starter-test with JUnit 5 - Stack Overflow):

A few additional notes to the ones mentioned by other contributors:

Using Spring Boot > 2.4.0

If you are using Spring Boot > 2.4.0, then there is nothing you have to do to use JUnit 5 Jupiter, because the spring-boot-starter-test library no longer includes the vintage-engine dependency (which transitively included JUnit 4), just include the starter dependency to the project and you're good to go. Use the useJUnitPlatform() in the Gradle configuration.

Using 2.4.0 > Spring Boot > 2.2.0

If you use earlier versions, I'd suggest using a version higher than 2.2.0.RELEASE, which is where the Spring team added support for JUnit 5 Jupiter into the spring-boot-starter-test by default.
In these versions, the library included the Vintage Engine dependency too, which could be used to run JUnit 4 tests using the JUnit 5 Jupiter platform. If you don't need to execute JUnit 4 tests, then the spring team suggests excluding org.junit.vintage:junit-vintage-engine (not just junit as indicated in the description):

testCompile('org.springframework.boot:spring-boot-starter-test') {
    exclude group: 'org.junit.vintage'
}

Here you would also need to configure the useJUnitPlatform() directive, of course.

二、Junit5的@ExtendWith不识别生效问题

1. 在不同的Spring Boot版本中@ExtendWith的使用也有所不同

其中在Spring boot 2.1.x之前: 

 @SpringBootTest 需要配合@ExtendWith(SpringExtension.class)才能正常工作的。

而在Spring boot 2.1.x之后: 

我们查看@SpringBootTest 的代码会发现,其中已经组合了@ExtendWith(SpringExtension.class),因此,无需在进行该注解的使用了,进一步简化。

2.1之后的@SpringBootTest源码如下: 

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@BootstrapWith(SpringBootTestContextBootstrapper.class)
@ExtendWith(SpringExtension.class)
public @interface SpringBootTest {
   @AliasFor("properties")
   String[] value() default {};
   @AliasFor("value")
   String[] properties() default {};
   Class[] classes() default {};

   WebEnvironment webEnvironment() default WebEnvironment.MOCK;

   enum WebEnvironment {
      MOCK(false),
      RANDOM_PORT(true), 
      DEFINED_PORT(true), 
      NONE(false);
      …
   }
}

2. 官方也给出了相应的说明:

If you are using JUnit 4, don’t forget to also add @RunWith(SpringRunner.class) to your test, otherwise the annotations will be ignored.
If you are using JUnit 5, there’s no need to add the equivalent @ExtendWith(SpringExtension.class) as @SpringBootTest and the other @…Test annotations are already annotated with it.

因此,在Spring Boot2.1.x之后单元测试可以简单的写成如下形式:

@SpringBootTest
public class OrderServiceTest {

   @Resource
   private OrderService orderService;

   @Test
   public void testInsert() {
      Order order = new Order();
      order.setOrderNo("A001");
      order.setUserId(100);

      orderService.insert(order);
   }
} 

相关文章:《SPRING BOOT JUNIT5单元测试注入BEAN抛NULLPOINTEREXCEPTION空指针异常》


部分参考自,对原文内容有增加:Spring boot junit5单元测试@ExtendWith无法工作 - 程序新视界 

你可能感兴趣的:(springBoot,JUnit,单元测试,junit,springboot,junit5)