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

bea*_*u13 5 junit spring spring-boot junit5

考虑以下测试类:

public class SomeClass {

    @Autowired
    private SomeDependency someDependency;

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

}
Run Code Online (Sandbox Code Playgroud)

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

dav*_*xxx 5

Mockito 1 runner(MockitoJUnitRunnerclass)不是为运行JUnit 5测试而设计的.

所以用以下内容注释你的课程:

import org.mockito.junit.MockitoJUnitRunner;

@RunWith(MockitoJUnitRunner.class) 
public class MyJUnit5Test {
Run Code Online (Sandbox Code Playgroud)

没有效果.

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

 MockitoAnnotations.initMocks(this);
Run Code Online (Sandbox Code Playgroud)

在使用JUnit 5注释的方法中@BeforeEach.
但是从现在开始,在每个JUnit测试类中不重复这种预处理的更好的替代方法是使用依赖MockitoExtension项提供mockito-junit-jupiter.


代码示例

假设SomeDependency该类声明为:

@Component
public class SomeDependency {

    public String returnThat() {
        return "that";
    }
}
Run Code Online (Sandbox Code Playgroud)

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

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

}
Run Code Online (Sandbox Code Playgroud)

注意,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>
Run Code Online (Sandbox Code Playgroud)

添加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>
Run Code Online (Sandbox Code Playgroud)

您不需要为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>
Run Code Online (Sandbox Code Playgroud)

它会生成一个Maven警告:

覆盖maven-surefire-plugin的托管版本2.20.1

好消息:从2.0.1.RELEASE版本的Spring Boot这个问题解决了,因为maven-surefire-plugin版本已更新使用2.21.0,后来的版本解决了这个问题.

  • 感谢您提供了很好的例子。我不知何故仍然得到一个“NullPointerException”(请参阅​​编辑)。顺便说一句:我正在尝试测试“SomeClass”,而不是“SomeDependency”。 (2认同)