如何在 junit 5 单元测试中为 @Autowired 模拟对象?

How to mock object for @Autowired in junit 5 unit test?

我正在使用 junit 5 对我的 spring 引导服务 class 进行单元测试。内部服务 class 我正在自动装配对象以调用其他 class 中的方法。在测试用例中,@Mock 没有为@Autowired class 创建对象。我在这里给出我的代码。

我的服务 class :

@Service
public class BarcodeReaderService {

    @Autowired
    ImageProcessor imageProcessor;

    public String dummy(String name) {
        System.out.println("function call"); //print success
        return imageProcessor.dummy(name);   //Null pointer Exception
    }
    }

我的组件 class :

@Component
public class ImageProcessor {

    public String dummy(String name) {
        // TODO Auto-generated method stub
        System.out.println("function call ImageProcessor"); //Not coming to this line
        return name;
    }
    }

我的单元测试class:

import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.junit.jupiter.MockitoExtension;
import com.inslab.reader.barcodereader.imageprocessing.ImageProcessor;
import com.inslab.reader.barcodereader.service.BarcodeReaderService;

@ExtendWith(MockitoExtension.class)
public class BarcodeReaderServiceTest {

    @InjectMocks
    BarcodeReaderService barcodeReaderService;

    @Mock
    ImageProcessor imageProcessor;


    @Test
    void testDummy() {
        Mockito.when(imageProcessor.dummy("name")).thenReturn("name");
        String name = barcodeReaderService.dummy("name");
        Assertions.assertEquals("name", name);
    }

}

pom.xml 文件:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.4.RELEASE</version>
        <relativePath /> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.inslab.reader</groupId>
    <artifactId>barcodereader</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>barcodereader</name>
    <packaging>jar</packaging>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>com.vaadin.external.google</groupId>
                    <artifactId>android-json</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

虽然 运行 这个测试我在 imageProcessor.dummy(name);

中得到空指针异常

您必须为您的测试注册 MocktioExtension,例如:

@ExtendWith(MockitoExtension.class)
public class BarcodeReaderServiceTest {

    @InjectMocks
    BarcodeReaderService barcodeReaderService;

    @Mock
    ImageProcessor imageProcessor;

    @Test
    void testDummy() {
        when(imageProcessor.dummy("name")).thenReturn("YOUR_OUTCOME");
        String name = barcodeReaderService.dummy("name");
        Assertions.assertEquals("YOUR_OUTCOME", name);
    }

}

也不要在测试中使用 new 来创建被测 class 的实例,而是使用字段变量 barcodeReaderService。当您使用 Mockito 时,您还必须指定 Mock 的行为,否则,它将始终 return null.

我在 class 的开头添加了@SpringBootTest。有效。确保您的导入对于 junit 5 是正确的。这是我的代码,

package com.inslab.reader;

import static org.junit.jupiter.api.Assertions.assertEquals;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.mock.web.MockMultipartFile;
import com.google.zxing.Result;
import com.inslab.reader.ImageProcessor;
import com.inslab.reader.IReader;

@SpringBootTest
class BarcodeReaderServiceTest {

    @InjectMocks
    BarcodeReaderService barcodeReaderService;

    @Mock
    ImageProcessor imageProcessor;

    @BeforeEach //instead of @Before have to use @BeforeEach in junit5
    public void setup() {
        MockitoAnnotations.initMocks(this);
    }

    @Test
    void testDummy() {
        Mockito.when(imageProcessor.dummy("name")).thenReturn("name");
        String name = barcodeReaderService.dummy("name");
        Assertions.assertEquals("name", name);
    }   
}

在测试class中为你的服务class使用@InjectMocks,你的服务class中的所有其他@Autowired在测试class[=中应该是@Mock 10=]