被测类
public class Student {
@Autowired
private Card card;
public boolean judgeNumber(Long uid) throws ServiceException {
if (uid.equals(-1)) {
throw new RuntimeException();
}
if (uid.equals(3)) {
return true;
}
card.isExist(null);
return false;
}
private boolean checkIsBlank(String name) {
return StringUtil.isBlank(name);
}
private void process(Long uid) throws ServiceException {
//doing
}
private void preProcess(String name, Long uid) {
checkIsBlank(name);
process(uid);
}
public static Integer add(Integer a, Integer b) {
return a + b;
}
}
一、TC的设计和命名
测试类的命名:
被测类名 + Test
eg:
被测类:Student
测试类:StudentTest
测试方法的命名:
test + 被测方法名 + [预期结果]
eg:
被测方法:judgeNumber
测试方法:testJudgeNumberTrue
二、TC的原理
调用被测方法,验证结果是否符合预期,中间如果有其他方法调用,需要打桩mock,专注测试本方法逻辑。
三、如何调用被测方法
1.测试公有方法
public class StudentTest {
@Mock
private Card card;
@InjectMocks
private Student student;
@Test
public void testJudgeNumberTrue() throws Exception {
boolean res = student.judgeNumber(3L);
Assert.assertTrue(res);
}
}
2.测试私有方法
@Test
public void testCheckIsBlank() throws Exception {
boolean res = Whitebox.invokeMethod(student, "check", any());
Assert.assertFalse(res);
}
3.测试静态方法
@Test
public void testAddSuccess() {
Assert.assertEquals(Integer.valueOf(2), Student.add(1, 1));
}
四、如何验证结果
1.assert对比输出结果
demo如上
常用断言验证
assertNotNull(Object) 是否为空
assertNull(Object) 是否为空
assertEquals(excepted, actual) 对象是否等值,期待值需要在前面
assertSame(excepted, actual) 对象是否相同
assertTrue(condition) 是否为true
assertFalse(condition) 是否为false
2.verify关键环节调用次数
@Test
public void testJudgeNumberFalse() throws Exception {
when(card.isExist(any())).thenReturn(null);
student.judgeNumber(2L)
verify(card, times(1)).isExist(any());
}
常用验证语句
验证是否被调用一次,等效于下面的times(1)
verify(student).add(1);
verify(student,times(1)).add(1);
验证是否被调用2次
verify(student,times(2)).add(2);
验证是否被调用3次
verify(student,times(3)).add(3);
验证是否从未被调用过
verify(student,never()).add(4);
验证至少调用一次
verify(student,atLeastOnce()).add(1);
验证至少调用2次
verify(student,atLeast(2)).add(2);
验证至多调用3次
verify(student,atMost(3)).add(3);
3.判断是否抛出异常
@Test(expected = RuntimeException.class)
public void testJudgeNumberException() throws Exception {
student.judgeNumber(-1L);
}
五、如何打桩
1.mock公有方法
@Test
public void testJudgeNumberFalse() throws Exception {
when(card.isExist(any())).thenReturn(null);
student.judgeNumber(2L);
}
2.mock私有方法
需要在测试类前加
@PrePareForTest(Student.class)
@Test
public void testPreProcess() throws Exception {
Student spy = PowerMockito.spy(student);
//mock无返回值的私有方法。
//doNothing() 可能会报错,这是由于mockito和powermock版本不匹配的原因。可以按照这个思路排查
PowerMockito.doNothing().when(spy, "process", anyLong());
//mock有返回值的私有方法
PowerMockito.doReturn(false).when(spy, "checkIsBlank",any());
//调用
Whitebox.invokeMethod(spy, "preProcess", null, null);
//验证
PowerMockito.verifyPrivate(spy, Mockito.times(1)).invoke("process", anyLong());
}
3.mock静态方法
需要在测试类前面加
@PrepareForTest(CommonUtil.class)
@Test
public void testMockStaticSuccess() throws Exception {
PowerMockito.mockStatic(CommonUtil.class);
when(CommonUtil.isOTO(any())).thenReturn(false);
}