技术选型:junit4+jmockit1.5+jacoco
Junit4用于编写单元测试,通过编写正常的业务流程,并进行相应的断言测试,来验证接口
JMockit是google code上面的一个java单元测试mock项目,它很方便地让你对单元测试中的final类,静态方法,构造方法进行mock,主要是通过jmockit模拟一个返回对象。
jacoco用于统计单元测试覆盖率
JMockit的测试方式可以通过下面2个途径实现
根据用例的测试路径,测试代码内部逻辑
由于被依赖代码可能在自己单测中已测试过,或者难以测试,就需要把这些被依赖代码的逻辑用预定期待的行为替换掉,也就是mock掉,从而把待测是代码隔离开,这也是单元测试的初衷。根据测试用例的输入输出数据,测试代码是否功能运行正常。
目的是从被测代码的使用角度出发,结合数据的输入输出来检验程序运行的这个正确性。使用这个方式,需要把被依赖的代码mock掉,实际上相当于改变了被依赖的代码的逻辑。通常在集成测试中,如果有难以调用的外部接口,就通过这个方式mock掉,模拟外部接口。一句话: @Injectable的实例会自动注入到@Tested中,如果没初始赋值,那么JMockit将会以相应规则初始化。JUnit4 与 JMock 的组合就成为 Java 开发人员写单元测试必备的利器。
JMockit有两种测试方式,一种是基于行为的,一种是基于状态的测试。
基于行为的mock,对mock目标代码的行为进行模仿,更像黑盒测试。基于状态的mock,是站在目标测试代码内部的。可以对传入的参数进行检查、匹配,才返回某些结果,类似白盒。
而基于状态的 new MockUp基本上可以mock任何代码或逻辑。
final UserBaseInfo userBaseInfo = new UserBaseInfo();
new NonStrictExpectations(){
{
new MockUp<SessionContainer>() {
@Mock
public SessionCache getSession() {
return new SessionCache();
}
}.getMockInstance();
new MockUp<SessionCache>() {
@Mock
public UserBaseInfo getUserBaseInfo() {
return userBaseInfo;
}
}.getMockInstance();
}
};
类命名和方法命名以Test结尾,方法添加注解@Test,需要引入的对象添加注解@Injectable
public class UserHeartRateServieTest{
@Injectable
private UserHeartRateResultDao userHeartRateResultDaoMock;
@Test
public void insertUserHeartRateTest(){
new NonStrictExpectations(){
{
userHeartRateResultDaoMock.insertUserHeartRateResult((UserHeartRateResult)any);
}
};
}
}
new NonStrictExpectations(){
{
userHeartRateResultDaoMock.selectByIdOrUserId(anyInt,anyInt);
result = userHeartRateResult;
userHeartRateDataDaoMock.getUserHeartRateDataListByGroupId(anyString);
result = list;
}
};
pom.xml单元测试配置
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.googlecode.jmockit</groupId>
<artifactId>jmockit</artifactId>
<version>1.5</version>
<scope>test</scope>
</dependency>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.7.4.201502262128</version>
<configuration>
<includes>
</includes>
<excludes>
</excludes>
</plugin>
Expectations与NonStrictExpectations
Expectations块里声明的mock方法,是一定要被执行的,如果没有被执行,会认为整个测试case不通过;NonStrictExpectations就没有这个限制
new Expectations(){
{
executorDao.getExecutorById(anyInt);
result = rtnMap;
teamDao.getTeamById(anyInt);
result = teamMap;
teamDao.getEnergyByGreenAreaId(anyInt);
result = 1;
}
};
对于需要引入工具类的代码行,可以作为参数传进来: