Document entry:
https://github.com/powermock/powermock/wiki
Private method mock documentation:
https://github.com/powermock/powermock/wiki/MockPrivate
Static method mock documentation
https://github.com/powermock/powermock/wiki/MockStatic
Overview:
Introduce common test methods based on Junit, Mockito, and PowerMockito, including exception testing, private method testing, method testing without return value, and mock or spy-based testing;
It contains regular method mocks and private method mocks.
A test introduction
1) Test principle:
Unit tests can be written for any method that needs to be verified to prove the expected behavior (no distinction between controller, service, dao)
2) Test classification:
a) Unit testing: Tests whether the "logic" of a method meets expectations.
b) Integration test: Integrate each dependent component to test whether the overall process can pass.
3) Regarding dependencies:
Unit testing generally tests the logic of the current method, not dependent class methods or its own private methods.
4) Difference between Mock and Spy generation classes
Mock: The generated class, all methods are not real methods, and the return value is NULL; behavior is specified by when.
Spy: In the generated class, all methods are real methods, and the return values are the same as real methods; a real method is replaced by the execution of the specified behavior through when.
5) Reference
1) Ordinary mockito mock
2) Use powerMock to enhance the ability of static methods and private methods;
https://github.com/powermock/powermock
Two Demo This program depends on
Xml code
<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">
<modelVersion>4.0.0</modelVersion>
<groupId>x.test</groupId>
<artifactId>test</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>test</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<junit.version>4.12</junit.version>
<mockito.version>2.8.47</mockito.version>
<powermock.version>1.7.0</powermock.version>
<assertj.version>3.8.0</assertj.version>
</properties>
<dependencies>
<!-- test -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>${mockito.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-module-junit4</artifactId>
<version>${powermock.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-api-mockito2</artifactId>
<version>${powermock.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>
<version>${assertj.version}</version>
<scope>test</scope>
</dependency>
<!-- utils -->
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>20.0</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
Three simple tests
Test throwing exceptions, method tests with no return value, private method tests
1) The class to be tested
Java code
package x.test.simple;
import com.google.common.base.Strings;
/**
* 测试demo class
* <p>
* Created by shilei on 2017/7/10.
*/
public class HelloWho {
private String who;
public HelloWho(String who) {
//条件路径
if (Strings.isNullOrEmpty(who)) {
throw new IllegalArgumentException("who can not be null!");
}
//赋值路径
this.who = who;
}
public void sayHello() {
System.out.println(getHelloMessage());
}
private String getHelloMessage() {
return "Hello " + who;
}
}
2) Test class
Java code
package x.test.simple;
import org.assertj.core.api.Assertions;
import org.junit.Test;
import org.powermock.reflect.Whitebox;
/**
* 基础测试:
* <p>
* 1 测试抛异常
* 2 测试无返回值
* 3 测试私有方法
*/
public class HelloWhoTest {
@Test(expected = IllegalArgumentException.class)
public void test_construction_empty_who_throw_exception() {
new HelloWho("");
}
@Test(expected = IllegalArgumentException.class)
public void test_construction_null_who_throw_exception() {
new HelloWho(null);
}
/**
* 无返回值的方法测试,查看其修改的成员变量是否成功
*/
@Test
public void test_construction_args_set_who() throws Exception {
//预期结果
String expectWho = "A";
//执行被测试方法
HelloWho helloWho = new HelloWho(expectWho);
//白盒,获取修改的成员变量
String actualWho = (String) Whitebox.getField(helloWho.getClass(), "who").get(helloWho);
//断言
Assertions.assertThat(actualWho).isEqualTo(expectWho);
}
/**
* 测试私有方法
*/
@Test
public void test_getHelloMessage() throws Exception {
//准备方法参数
String who = "A";
//准备预期结构
String expextMessage = "Hello " + who;
//执行被测试方法
HelloWho helloWho = new HelloWho(who);
String actualMessage = Whitebox.invokeMethod(helloWho, "getHelloMessage");
//断言
Assertions.assertThat(actualMessage).isEqualTo(expextMessage);
}
}
Four Mock-based tests
Depend on mock, private method mock, verify whether the method is executed
1) Dependent class Dao
Java code
package x.test.adv.dao.pojo;
/**
* 用户
* <p>
* Created by shilei on 2017/7/10.
*/
public class User {
}
package x.test.adv.dao;
import x.test.adv.dao.pojo.User;
/**
* 用户dao
* Created by shilei on 2017/7/10.
*/
public interface UserDao {
/**
* 保存
*
* @param user 用户
* @return true : 保存成功 ; false : 用户已存在
*/
boolean save(User user);
}
2) Service to be tested
Java code
package x.test.adv.service;
import x.test.adv.dao.pojo.User;
/**
* 用户服务
* <p>
* Created by shilei on 2017/7/10.
*/
public interface UserService {
/**
* 保存 , 如果保存成功,记录日志
*
* @param user user
*/
void save(User user);
}
package x.test.adv.service.impl;
import x.test.adv.dao.UserDao;
import x.test.adv.dao.pojo.User;
import x.test.adv.service.UserService;
/**
* 带依赖的测试
* <p>
* Created by shilei on 2017/7/10.
*/
public class UserServiceImpl implements UserService {
private UserDao userDao;
@Override
public void save(User user) {
//保存
boolean isSave = userDao.save(user);
//写大数据日志
if (isSave) {
writeLog(user);
}
}
private void writeLog(User user) {
System.out.println(user);
}
}
3) Test class
Java code
package x.test.adv.service.impl;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import x.test.adv.dao.UserDao;
import x.test.adv.dao.pojo.User;
/**
* 带依赖的测试:
* 1 mock 依赖
* 2 mock 私有方法
*/
@RunWith(PowerMockRunner.class)
//mock 静态方法,私有方法,需要添加该注解,以便通知框架
@PrepareForTest(UserServiceImpl.class)
public class UserServiceImplTest {
//mock 依赖注入到该bean
@InjectMocks
private UserServiceImpl userServiceImpl;
//mock 依赖
@Mock
private UserDao userDao;
//完成依赖注入
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
}
/**
* 测试保存成功,写日志
*/
@Test
public void test_save_true_verify_writelog() throws Exception {
// 侦查对象
UserServiceImpl spyUserService = PowerMockito.spy(userServiceImpl);
//创建输入
User user = new User();
//打桩
// mock 依赖行为,等价于 BDDMockito.given(userDao.save(user)).willReturn(true);
Mockito.when(userDao.save(user)).thenReturn(true);
//mock 私有方法
PowerMockito.doNothing().when(spyUserService, "writeLog", user);
//调用实际方法
spyUserService.save(user);
//断言 writelog 被执行一次
PowerMockito.verifyPrivate(spyUserService, Mockito.times(1)).invoke("writeLog", user);
}
/**
* 测试保存成功,写日志
*/
@Test
public void test_save_false_no_writelog() throws Exception{
// 侦查对象
UserServiceImpl spyUserService = PowerMockito.spy(userServiceImpl);
//创建输入
User user = new User();
//打桩
// mock 依赖行为,等价于 BDDMockito.given(userDao.save(user)).willReturn(true);
Mockito.when(userDao.save(user)).thenReturn(false);
//mock 私有方法
PowerMockito.doNothing().when(spyUserService, "writeLog", user);
//调用实际方法
spyUserService.save(user);
//断言 writelog 被执行一次
PowerMockito.verifyPrivate(spyUserService, Mockito.times(0)).invoke("writeLog", user);
}
}