Spring Boot 2 应用程序的 JUnit 5 测试中的模拟自动装配依赖项

Mock autowired dependency in JUnit 5 test for Spring Boot 2 app

考虑以下 class 测试:

public class SomeClass {

    @Autowired
    private SomeDependency someDependency;

    public int inc(int i) {
        someDependency.doSomething();
        return i + 1;
    }

}

如何在 JUnit 5 (5.0.1) 测试 Spring Boot 2 (2.0.0.M2) 应用程序中模拟(最好使用 Mockito)someDependency?当我尝试调用 SomeClass#inc(int) 时,它会产生一个 NullPointerException 因为没有注入自动装配的依赖项。

Mockito 1 运行ner (MockitoJUnitRunner class) 不是为 运行 JUnit 5 测试而设计的。

所以用 :

注释你的 class
import org.mockito.junit.MockitoJUnitRunner;

@RunWith(MockitoJUnitRunner.class) 
public class MyJUnit5Test {

不会有任何影响。

为了能够使用 @Mock 注释,您可以在每次测试之前调用 :

 MockitoAnnotations.initMocks(this);

在使用 JUnit 5 注释的方法中 @BeforeEach
但是从现在开始,在每个 JUnit 测试 class 中不重复此预处理的更好替代方法是使用 MockitoExtension class provided by the mockito-junit-jupiter dependency


代码示例

假设 SomeDependency class 声明为:

@Component
public class SomeDependency {

    public String returnThat() {
        return "that";
    }
}

您可以在单元测试中以这种方式模拟依赖关系:

import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.junit.jupiter.MockitoExtension;

import davidhxxx.example.angularsboot.SomeDependency;

@ExtendWith(MockitoExtension.class)    
public class SomeClassTest {

    @Mock
    SomeDependency someDependencyMock;

    private SomeClass someClass;

    @BeforeEach
    public void setup(){
      someClass = new SomeClass(someDependencyMock);
    }

    @Test 
    void myFirstTest() {
      Mockito.when(someDependencyMock.returnThat()).thenReturn("mock result");
      Assertions.assertEquals("mock result", someClass.inc());
    }

}

请注意 SomeClass 必须提供一种设置其 SomeDependency 依赖项的方法。
您应该添加一个接受 .
实例的构造函数 使用 setter 也是一种方法,同时它提供了可变性。


pom.xml 要求

1) 您可以添加 the spring-boot-starter-test 依赖,包括 Mockito 和继承依赖中的其他有用的东西:

<dependencies>
    ...
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
   ...
</dependencies>

还添加 junit-jupiter-engine 依赖项和您需要的所有其他可选 JUnit 5 依赖项:

<dependencies>
    ...
    <dependency>
        <groupId>org.junit.jupiter</groupId>
        <artifactId>junit-jupiter-engine</artifactId>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.mockito</groupId>
        <artifactId>mockito-junit-jupiter</artifactId>
        <version>2.18.0</version> <!-- version to specify as not provided by Spring Boot dependencies -->
        <scope>test</scope>
    </dependency>
</dependencies>

您不需要为 junit-jupiter-engine 工件指定版本,但您可能需要为其他 JUnit 5 依赖项指定版本,例如 junit-jupiter-params.
希望在下一版本的 Spring Boot.

中不再需要这样做

2) 小心:如果您使用 Spring 启动版本 2.20版本的maven-surefire-plugin就不行了。因此,您必须覆盖 maven-surefire-plugin 插件配置以指定与 JUnit 5 兼容的版本(即 2.19 或 2.21 及更高版本)。
例如 Spring Boot 的 2.0.0.M5 版本会拉取 maven-surefire-plugin:2.20,因此需要重新配置插件,如下所示:

    <plugins>
        ...
        <plugin>
            <artifactId>maven-surefire-plugin</artifactId>
            <version>2.19</version>
            <dependencies>
                <dependency>
                    <groupId>org.junit.platform</groupId>
                    <artifactId>junit-platform-surefire-provider</artifactId>
                    <version>1.0.0</version>
                </dependency>
            </dependencies>
        </plugin>
     ...
   <plugins>

它将生成 Maven 警告:

Overriding managed version 2.20.1 for maven-surefire-plugin

好消息:从 Spring 的 2.0.1.RELEASE 版本开始,此问题已解决,因为 maven-surefire-plugin 版本已更新为使用 2.21.0 及更高版本解决了这个问题。