1. jar 包选择
<!-- 单侧相关 统一管理 -->
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-all</artifactId>
<version>${mockito.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>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.3.19</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-api-mockito</artifactId>
<version>1.6.3</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-module-junit4</artifactId>
<version>1.6.3</version>
<scope>test</scope>
</dependency>
2. 要测试的目标方法, 注意是私有方法
以及这个方法里再次调用的方法, 这个方法是查询数据库方法
3. 单元测试的编写
说几点编写单元测试类的注意事项 :
1. @InjectMocks 标注的字段会创建一个实例, 其余用 @Mock(或@Spy)注解创建的 mock 字段将被注入到该实例中
2. 在这个测试类中, sqpDmUserRelationService 的实例会被注入到 decisionFlowService, 类似在业务层里注入dao层对象
3. 因为要测试的代码里有数据库查询的操作, 但是我们写的是单侧, 不会真正的查询数据库, 所以需要自己 mock 数据库查询的数据, 首先创建一个集合, 在集合里添加对象, 用于表示这是查询数据库后会返回的数据
之后这行代码很关键
when(sqpDmUserRelationService.getUserGroupInfo(any())).thenReturn(sqpDmUserRelationList);
这行代码表示调用 getUserGroupInfo() 方法, 使用任意参数 any(), 模拟数据库查询,
之后返回我们刚才创建的集合, 这样就完成了模拟数据库的查询, 后面这个查询结果还会使用到
4. 创建执行目标方法的对象, 由于我们本次测试的是私有方法, 这种情况在项目会有很多, 所以需要使用PowerMock框架, 并且使用 PowerMockito.spy(decisionFlowService) 方法, 参数一定要传递我们刚才用 @InjectMocks 创建的实体字段对象, 这样会把 decisionFlowService 对象引用和 sqpDmUserRelationService 对象引用都传递到我们要测试的目标方法里
5. 执行目标方法, PowerMockito.when(spy, "getUserGroupDynamicSql", "城市", 1).thenReturn(Lists.newArrayList());
使用 PowerMockito,when() 执行目标方法, 第一个参数是代理对象, 第二个参数是我们要调用的私有方法的方法名称, 第三个参数是方法的参数
@RunWith(MockitoJUnitRunner.class)
@PrepareForTest({DecisionFlowServiceImpl.class, SqpDmUserRelationServiceImpl.class, SqpDmUserRelationService.class})
public class DecisionFlowServiceImplTest {
@Mock
private SqpDmUserRelationServiceImpl sqpDmUserRelationService;
@InjectMocks
private DecisionFlowServiceImpl decisionFlowService;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
}
@Test
public void testGetCountDecisionFlowNum() throws Exception {
// 模拟mysql数据
List<SqpDmUserRelation> sqpDmUserRelationList = Lists.newArrayList();
SqpDmUserRelation var1 = new SqpDmUserRelation();
var1.setEmployeeCode("060423665");
var1.setDutyType("大区");
var1.setDutyValue("东区");
sqpDmUserRelationList.add(var1);
SqpDmUserRelation var3 = new SqpDmUserRelation();
var3.setEmployeeCode("060423665");
var3.setDutyType("店铺区");
var3.setDutyValue("AD11111");
sqpDmUserRelationList.add(var1);
SqpDmUserRelation var2 = new SqpDmUserRelation();
var2.setEmployeeCode("210902495");
var2.setDutyType("店铺");
var2.setDutyValue("AD1111");
sqpDmUserRelationList.add(var2);
// mock mysql查询
when(sqpDmUserRelationService.getUserGroupInfo(any())).thenReturn(sqpDmUserRelationList);
// 调用目标方法
DecisionFlowServiceImpl spy = PowerMockito.spy(decisionFlowService);
PowerMockito.when(spy, "getUserGroupDynamicSql", "城市", 1).thenReturn(Lists.newArrayList());
}
}
4. 断点测试执行情况
在目标方法打断点, 查看单元测试的执行情况
首先观察使用了 @InjectMocks 注解声明的字段, 可以看到是实例对象, 在这个对象里, 还注入了@Mock 帮我们生成的代理对象
其次是模拟数据库查询的情况, 可以看到集合里有数据, 并且都是我们在单元测试代码里自己模拟的数据, 这里我们没有建立数据库连接, 并查询数据库, 但是可以使用 mock 框架模拟查询, 拿到数据, 之后就可以对这些模拟的数据, 做之后的业务处理