本文通过一些java mock测试的例子简单讲解一下如何使用java mock进行测试。
1.准备工作
a.基于maven在pom.xml中添加如下依赖(包含了mock以及powermock):
<dependencies>
<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
<version>6.9.10</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>2.0.42-beta</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-core</artifactId>
<version>1.6.5</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-api-mockito2</artifactId>
<version>1.6.5</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-module-testng</artifactId>
<version>1.6.5</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
<version>2.6</version>
<scope>provided</scope>
</dependency>
</dependencies>
b.建立Controller类(主要功能是字符串解析并返回或者封装结果):
package com.zhq.controller;
import java.util.HashMap;
import java.util.Map;
import com.zhq.bean.PersonInfo;
import com.zhq.common.CommonUtils;
import com.zhq.dao.PersonQueryDao;
public class InfoController {
/**
* 负责将parameters中的key1:value1,key2:value2的数据解析并放置到result中
* @param parameters
* @param keys
* @return
*/
public Map<String, String> packageInfos(String parameters, String... keys) {
Map<String, String> result = new HashMap<String, String>();
if (CommonUtils.verifyParameters(result, parameters, keys)) {
return result;
}
return null;
}
/**
*
* 负责判断参数的合法性并将参数内容封装到PersonInfo中
* @param name
* @param age
* @return
*/
public PersonInfo packageIntoPerson(String name, String age) {
PersonQueryDao dao = new PersonQueryDao();
return dao.query(name, age);
}
}
c.Controller类中使用的公共类CommonUtils:
package com.zhq.common;
import java.util.HashMap;
import java.util.Map;
import org.apache.commons.lang.StringUtils;
public class CommonUtils {
/**
* 负责将parameters中的key1:value1,key2:value2的数据解析并放置到result中
* @param result 解析后的结果Map
* @param parameters 要解析的参数
* @param keys 要解析的key
* @return
*/
public static boolean verifyParameters(Map<String, String> result,
String parameters, String...keys) {
Map<String, String> parameterMap = new HashMap<String, String> ();
if (StringUtils.isBlank(parameters) || keys == null || keys.length == 0) {
return false;
}
String[] splitParameters = parameters.split(",");
String oneSplitted[] = null;
for (String splitted : splitParameters) {
oneSplitted = splitted.split(":");
if (oneSplitted.length < 2) continue;
parameterMap.put(oneSplitted[0], oneSplitted[1]);
}
for (String key : keys) {
if (!parameterMap.containsKey(key)) {
return false;
}
result.put(key, parameterMap.get(key));
}
return true;
}
}
d.Controller类中使用的查询类PersonQueryDao:
package com.zhq.dao;
import org.apache.commons.lang.StringUtils;
import com.zhq.bean.PersonInfo;
public class PersonQueryDao {
/**
* 跟据名字和年龄查询并返回个人信息
* @param name
* @param age
* @return
*/
public PersonInfo query(String name, String age) {
if(StringUtils.isEmpty(name) || StringUtils.isEmpty(age)) {
return null;
}
PersonInfo person = new PersonInfo();
person.setName(name);
person.setAge(age);
return person;
}
}
e.Controller中使用的bean类PersonInfo:
package com.zhq.bean;
public class PersonInfo {
private String name;
private String age;
public void setName(String name) {
this.name = name;
}
public String getName() {
return this.name;
}
public void setAge(String age) {
this.age = age;
}
public String getAge() {
return this.age;
}
}
2.对InfoController类进行测试(测试代码在src/test/java中)
主要包含的知识点是:如何对调用静态方法的类进行mock;如何注入mock,并进行真实调用;如何使用mock来模拟调用对象中的函数;如何在mock测试中使用反射机制将结果填入参数中。测试代码如下:
package com.zhq.controller;
import java.util.Map;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.testng.PowerMockTestCase;
import org.testng.Assert;
import org.testng.annotations.Test;
import com.zhq.bean.PersonInfo;
import com.zhq.common.CommonUtils;
import com.zhq.dao.PersonQueryDao;
//对于测试过程中使用到static函数的调用,先将调用static函数的类准备好
@PrepareForTest({ CommonUtils.class })
public class InfoControllerTest extends PowerMockTestCase {
//注入式的mock,用于真实调用
@InjectMocks
private InfoController infoController = new InfoController();
//使用@Mock模拟调用对象中的函数
@Mock
private PersonQueryDao personDao;
/**
* 测试InfoController中的packageInfos
*/
@Test
public void packageInfosTest() {
//在函数调用中使用CommonUtils类的静态方法需要先mockStatic一下CommonUtils
PowerMockito.mockStatic(CommonUtils.class);
//测试返回结果为空
Mockito.when(CommonUtils.verifyParameters(Mockito.anyMapOf(String.class, String.class), Mockito.anyString(), Mockito.anyString(), Mockito.anyString())).thenReturn(false);
Assert.assertEquals(infoController.packageInfos("name:zhq,age:30", "name", "age"), null);
//测试返回结果非空
//因为要模拟将CommonUtils.verifyParameters的结果放入Map中并返回,所以使用thenAnswer采用反射的方式将结果填入
Mockito.when(CommonUtils.verifyParameters(Mockito.anyMapOf(String.class, String.class), Mockito.anyString(), Mockito.anyString(), Mockito.anyString())).thenAnswer(new Answer<Boolean>() {
public Boolean answer(InvocationOnMock invocation) throws Throwable {
@SuppressWarnings("unchecked")
Map<String,String> result = (Map<String,String>) invocation.getArguments()[0];
result.put("name", "zhq");
result.put("age", "30");
return true;
}
});
Map<String,String> result = infoController.packageInfos("name:zhq,age:30", "name", "age");
Assert.assertEquals(result.get("name"), "zhq");
Assert.assertEquals(result.get("age"), "30");
}
/**
* 测试InfoController中的packageIntoPerson
*/
@Test
public void packageIntoPersonTest() {
//测试返回null
Mockito.when(personDao.query(Mockito.anyString(), Mockito.anyString())).thenReturn(null);
Assert.assertEquals(infoController.packageIntoPerson("zhq", null), null);
//测试返回非null
Mockito.when(personDao.query(Mockito.anyString(), Mockito.anyString())).thenReturn(new PersonInfo());
Assert.assertNotNull(infoController.packageIntoPerson("zhq", "age"));
}
}
3.对CommonUtils类进行测试(测试代码在src/test/java中)
主要包含的知识点是:怎样对静态函数进行测试
package com.zhq.common;
import java.util.HashMap;
import java.util.Map;
import org.powermock.modules.testng.PowerMockTestCase;
import org.testng.Assert;
import org.testng.annotations.Test;
public class CommonUtilsTest extends PowerMockTestCase {
@Test
public void verifyParametersTest() {
Map<String,String> result = new HashMap<String,String> ();
//测试parameters为null
Assert.assertEquals(CommonUtils.verifyParameters(result, null, "abc"), false);
//测试keys为null
Assert.assertEquals(CommonUtils.verifyParameters(result, "name:zhq,age:30", null), false);
//测试keys为""
Assert.assertEquals(CommonUtils.verifyParameters(result, "name:zhq,age:30", ""), false);
//测试parameters中的键值与keys不匹配
Assert.assertEquals(CommonUtils.verifyParameters(result, "name:zhq,age:30", "name,height"), false);
//测试parameters中的键值与keys不匹配
Assert.assertEquals(CommonUtils.verifyParameters(result, "name:zhq,age:30", "name"), true);
Assert.assertEquals(result.get("name"), "zhq");
}
}