Java Mockito 笔记


Mockito


1 Overview

2 Maven 项目初始化

3 示例

        3.1 第一个示例

        3.2 自动 Mock

        3.3 Mock 返回值

        3.4 Mock 参数

        3.5 自动注入 Mock 对象

        3.6 验证调用次数

        3.7 预设 Exception

        3.8 Void Mock

        3.9 级联 Mock

        3.10 部分 Mock

4 FAQ

        4.1 注意点

5 References


pom.xml

<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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	>4.0.0>

	>com.lld>
	>test.mockito>
	>0.0.1-SNAPSHOT>
	>jar>

	>test.mockito>
	>http://maven.apache.org
	>
		>org.springframework.boot>
		>spring-boot-starter-parent>
		>1.5.4.RELEASE>
	>

	>
		.build.sourceEncoding>UTF-8.build.sourceEncoding>
	>

	>
		>
			>org.springframework.boot>
			>spring-boot-starter>
		>
        >
            >org.springframework.boot>
            >spring-boot-starter-test>
        >
		>
			>org.mockito>
			>mockito-all>
			>1.9.5>
			>test>
		>
	>
	>
		>
			>
				>org.springframework.boot>
				>spring-boot-maven-plugin>
			>
		>
	>
>

MainService.java

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class MainService {
    @Autowired
    OtherService otherService;
    
    public void call() {
        System.out.println("value is: " + otherService.getValue());
    }
}

OtherService.java

import org.springframework.stereotype.Component;

@Component
public class OtherService {
    public String getValue() {
        return "real value";
    }
}

常规情况下,我们需要手工注入 Mock 对象,如下所示:

AutoInjectTest.java

import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = DemoConfig.class)
public class AutoInjectTest {
    @Autowired
    MainService service;
    
    @Mock
    OtherService otherService;
    
    @Test
    public void manualInjectTest() {
        otherService = mock(OtherService.class);
        when(otherService.getValue()).thenReturn("mock value");
        service.setOtherService(otherService);
        service.call();
    }
}

PS:需要在 MainService 类中添加 setOtherService() 方法以允许修改 otherService

其中 DemoConfig 是配置类,对于 Spring Boot 框架,Test 类不会自动注入 Autowired 对象,需要使用 Config 类指定加载类,内容如下:

DemoConfig.java

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@Configuration
@ComponentScan({ "com.lld.test" })
public class DemoConfig {

}

但更合理的方式是使用 @InjectMocks 注解来自动注入,如下所示

AutoInjectTest.java

import static org.mockito.Mockito.when;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = DemoConfig.class)
public class AutoInjectTest {
    @Autowired
    @InjectMocks
    MainService service;
    
    @Mock
    OtherService otherService;
    
    @Before
    public void setup() {
        MockitoAnnotations.initMocks(this);
        when(otherService.getValue()).thenReturn("mock value");
    }
    
    @Test
    public void autoInjectTest() {
        service.call();
    }
}

注意如下几点:

  • 在 @Before 方法中初始化 Mock 对象及自动注入
  • 在需要自动注入成员的类上添加 @InjectMocks 注解

另外值得注意的是,@InjectMocks 只会注入当前对象的成员,不会递归深度注入对象,例如,我们如果将 MainService 修改如下:

MainService.java

@Component
public class MainService {
    @Autowired
    MiddleService middleService;

    public void callMiddle() {
        System.out.println("value is: " + middleService.getValue());
    }
}

添加 MiddleService 如下所示

MiddleService.java

@Component
public class MiddleService {
    @Autowired
    OtherService otherService;

    public String getValue() {
        return otherService.getValue();
    }
}

这样的话,Unit Test 需要修改如下:

AutoInjectTest.java

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = DemoConfig.class)
public class AutoInjectTest {
    @Autowired
    MainService service;

    @Mock
    OtherService otherService;
    
    @Autowired
    @InjectMocks
    MiddleService middleService;

    @Before
    public void setup() {
        MockitoAnnotations.initMocks(this);
        when(otherService.getValue()).thenReturn("mock value");
    }

    @Test
    public void autoInjectDeepTest() {
        service.callMiddle();
    }
}

Mockito 1.x

Mockito 2.x

How to mock with Mockito