本文包含了一些我个人认为使用Mockito和PowerMockito可能碰到的问题的解决方法(以下所有代码的运行前提是你已经配置好Mockito,PowerMockito的jar包)
------------------------------------------------------------------------------------------------------------------------------------------------------------------
package com.ray.mockito_demo1.present;
import static org.mockito.Mockito.*;
import java.util.Iterator;
import java.util.List;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.runners.MockitoJUnitRunner;
import com.ray.entity.Goods;
@RunWith(MockitoJUnitRunner.class)
public class MockitoTest {
/**
* 初始测试数据
*/
@Before
public void setUp() {
// 初始化mock测试数据
g1 = mock(Goods.class);
list = mock(List.class);
when(g1.getName()).thenReturn("iPhone10s plus");
when(list.size()).thenReturn(1);
when(list.get(0)).thenReturn(g1);
}
/**
* 测试 List.class
*/
@Test
public void testList() {
// execute 执行测试方法
int size = list.size();
for (int i = 0; i < size; i++)
System.out.println("goods name=" + list.get(i).getName());
// verify 验证期望调用的方法, verify(mock)方法的参数必须是Mock对象,
// 当参数只有一个的时候, 等价于verify(mock, times(1)), 没有设置第二个参数
// 的时候默认调用一次; verify(mock, never()), 验证方法是否没有调用过
verify(list).size(); // 验证goodsList.size()调用了一次
verify(list).get(0); // 验证goodsList.get(0)调用了一次
verify(g1).getName();// 验证goods1. getName ()没有调用过
}
/**
* 增强型for循环
* 因为增强型for循环会调用Iterator的hasNext(), next()方法,
* 所以我们需要mock一个Iterator, 并为这两个方法的调用做预设;
* 如果不设置Iterator的话, 会得到一个NullPointerException;
*/
@Test
public void testAdvancedForLoop() {
Iterator
when(list.iterator()).thenReturn(itr);
// 第一次调用返回true,第二次调用返回false, 因为集合里面只有一个Goods;
// 如果不设置thenReturn(false)的话将会产生死循环
when(itr.hasNext()).thenReturn(true).thenReturn(false);
when(itr.next()).thenReturn(g1);
// 执行测试
for(Goods g : list)
System.out.println("Congratrulations! you get one [" + g.getName() + "].");
//verify
verify(list).iterator();
verify(itr, times(2)).hasNext();
verify(g1).getName();
}
private Goods g1;
private List
}
------------------------------------------------------------------------------------------------------------------------------------------------------------------
package com.ray.mockito_demo1.present;
import static org.junit.Assert.*;
import static org.mockito.Mockito.*;
import org.powermock.api.mockito.PowerMockito;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
/**
* PowerMockito模拟private, static, 构造方法
*
* PowerMockito.verifyPrivate(...) 验证私有方法的调用
* PowerMockito.mockStatic(...) 模拟静态方法
*
* @author ray.sun
*/
@RunWith(PowerMockRunner.class)
/* 声明需要模拟的类 */
@PrepareForTest(OutMan.class)
public class PowerMockitoTest {
/**
* 模拟私有(private)方法
* @throws Exception
*/
@Test
public void testPrivateMethod() throws Exception {
PowerMockito.doReturn(10).when(oman, "charge", anyInt());
assertEquals(10, oman.fightTime(999));
PowerMockito.verifyPrivate(oman, times(1)).invoke("charge", 999);
}
/**
* 模拟静态(static)方法
*/
@Test
public void testStaticMethod(){
PowerMockito.mockStatic(OutMan.class);
when(OutMan.sleepTime()).thenReturn(0);
assertEquals(0, OutMan.sleepTime());
}
/**
* 模拟构造器
* @throws Exception
*/
@Test
public void testConstructor() throws Exception{
oman = mock(OutMan.class);
//stub
PowerMockito.whenNew(OutMan.class).withNoArguments().thenReturn(oman);
PowerMockito.whenNew(OutMan.class).withArguments(anyDouble(), anyDouble()).thenReturn(oman);
//verify
assertEquals(oman, new OutMan());
assertEquals(oman, new OutMan(20, 50));
}
private OutMan oman = PowerMockito.spy(new OutMan());
}
class OutMan {
public OutMan() {}
public OutMan(double height, double weight) {
this.height = height;
this.weight = weight;
}
public static int sleepTime(){
return 8;
}
public int fightTime(int chargeTime){
return charge(chargeTime);
}
/**
* return the time that outman can fight
*/
private int charge(int chargeTime) {
if (0 == chargeTime)
return 1;
return chargeTime * 1000;
}
private double height;
private double weight;
}
------------------------------------------------------------------------------------------------------------------------------------------------------------------
package com.ray.mockito_demo1.present;
import static org.mockito.Mockito.*;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import com.ray.mockito_demo1.present.TaskList.Callback;
@RunWith(PowerMockRunner.class)
/* 声明需要模拟的类*/
@PrepareForTest(fullyQualifiedNames="com.ray.mockito_demo1.present.MySchedule*")
public class PowerMockitoTest2 {
@InjectMocks
private MySchedule mySchedule;
@Mock
private TaskList taskList;
@Mock
private Task1 task1;
/**
* 在匿名内部类里面模拟构造器
* @throws Exception
*/
@Test
public void testConstructOfAnoymousInnerClass() throws Exception{
PowerMockito.whenNew(Task1.class).withNoArguments().thenReturn(task1);
doCallRealMethod().when(taskList).handle(any(TaskList.Callback.class));
mySchedule.process();
verify(task1).execute();
}
}
class MySchedule {
public void process(){
new TaskList().handle(new Callback(){
public void execute() {
new Task1().execute();
}});
}
}
class TaskList {
void handle(Callback callback){
callback.execute();
};
public static interface Callback {
public void execute();
}}
class Task1{
public void execute(){
System.out.println("Task1 completed.");
}}
----------------------------------------------------------------------Goods.java----------------------------------------------------------------------------
package com.ray.entity;
public class Goods {
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
private String name;
}
-----------------------------------------------------------------------pom.xml------------------------------------------------------------------------------
UTF-8
1.9.5
1.5.5
org.mockito
mockito-all
${mockito.version}
test
org.powermock
powermock-module-junit4
${powermock.version}
org.powermock
powermock-api-mockito
${powermock.version}