【问题标题】:How to mock object for @Autowired in junit 5 unit test?如何在junit 5单元测试中模拟@Autowired的对象?
【发布时间】:2020-06-30 07:22:45
【问题描述】:

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

我的服务等级:

@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
    }
    }

我的组件类:

@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;
    }
    }

我的单元测试类:

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); 中得到空指针异常;

【问题讨论】:

  • 当然,当您在测试方法中创建一个新实例时,您会得到一个 nullpointerexpeption,而不是重用注入了模拟的类中的实例。使用SpringExtension 运行它也不会添加任何内容,因为这不是基于弹簧的测试,而是常规的单元测试。
  • 我删除了这个 BarcodeReaderService barcodeReaderService = new BarcodeReaderService();从测试。错误不是预期的,而是:。如果我尝试删除这个@ExtendWith(SpringExtension.class),我在这一行字符串名称=barcodeReaderService.dummy("name");.中得到空指针异常
  • 您不仅删除了扩展,而且您的设置方法也不见了,它应该仍然在那里设置您的模拟。
  • 好的,我也会添加并检查。

标签: spring-boot unit-testing junit5


【解决方案1】:

您必须为您的测试注册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 来创建您的测试类的实例,而是使用您的字段变量barcodeReaderService。当您使用 Mockito 时,您还必须指定 Mock 的行为,否则,它将始终返回 null

【讨论】:

  • 我也做了同样的事情。现在我得到失败跟踪 - java.lang.NoSuchMethodError: org.junit.platform.commons.support.AnnotationSupport.findAnnotation(Ljava/util/Optional;Ljava/lang/Class;)Ljava/util/Optional;在 org.mockito.junit.jupiter.MockitoExtension.retrieveAnnotationFromTestClasses(MockitoExtension.java:183)
  • 确保在您的测试中只使用 JUnit 5,并且不要从 org.junit 而是从 org.junit.jupiter 导入任何东西,因为 @Test 注释可能仍然来自 JUnit 4
  • 如果这没有帮助,请将您的pom.xml 和您的测试类的完整代码(包括导入部分)添加到您的问题中
  • 我添加了我的 pom.xml 和测试类的导入
  • 好的,目前的错误是什么:空指针或 NoSuchMethodErrod?
【解决方案2】:

我在课程开始时添加了@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);
    }   
}

【讨论】:

    【解决方案3】:

    在测试类中为您的服务类使用@InjectMocks,服务类中的所有其他@Autowired 在测试类中应为@Mock

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-22
      • 1970-01-01
      • 2020-02-07
      • 2019-01-22
      相关资源
      最近更新 更多