Mockito可以做哪些事情
1.验证行为
@Test
public void verify_behaviour() {
List mock = mock(List.class);
// 使用mock对象执行操作
mock.add(1);
mock.clear();
// 验证操作是否执行
verify(mock).clear();
verify(mock).add(1);
}
注意:verify验证操作是否执行,并不关心顺序;但是如果需要顺序上的验证,那么就需要每操作一步就验证一步
2.模拟期望的结果
@Test
public void when_andReturn() {
Iterator mock = mock(Iterator.class);
//模拟期望的结果
when(mock.next()).thenReturn("first").thenReturn("2_n_time").thenReturn("haha");
//实际执行的结果
String actual = mock.next() + "\n" + mock.next() + "\n"+"haha";
//断言
assertEquals("first\n2_n_time\nhaha", actual);
}
3.模拟方法体抛出异常
@Test(expected = RuntimeException.class)
public void exceptionTest(){
List mock = mock(List.class);
// 模拟抛出异常
doThrow(new RuntimeException()).when(mock).add(1);
mock.add(1);
}
4.使用注解快速模拟
@Mock
public Map mockMap;
@Before
public void setData(){
mockMap = new HashMap();
}
说明:使用Mock注解来创建对象,不过需要自己来new实现类;并且会有很多限制,使用时需要注意
5.参数匹配
@Test
public void argsMatch(){
Map map = mock(Map.class);
//模拟当 map put 时返回 1
when(map.put(anyString(),anyInt())).thenReturn(1);
map.put("2",2);
Integer rt= 1;
verify(map).put("2",2);
//断言put 的返回值
assertEquals(rt, map.put("2",2));
}
说明:anyInt(),anyString() …可以匹配任意参数
6.期望异常
-
@Test(expected…)
@Test注解有一个可选的参数,”expected”允许你设置一个Throwable的子类。如果你想要验证上面的canVote()方法抛出预期的异常,我们可以这样写:
@Test(expected = IllegalArgumentException.class ) public void canVote_throws_IllegalArgumentException_for_zero_age() { Student student = new Student(); student.canVote("0"); }
-
ExpectedException
如果要使用JUnit框架中的ExpectedException类,需要声明ExpectedException异常
@Rule public ExpectedException thrown= ExpectedException.none();
然后你可以使用更加简单的方式验证预期的异常
@Test public void canVote_throws_IllegalArgumentException_for_zero_age() { Student student = new Student(); thrown.expect(IllegalArgumentException.class ); thrown.expectMessage("your exception msg"); student.canVote( 0 ); }
7.使用 PowerMock来 mock protected 和 private 方法
@RunWith(PowerMockRunner.class)
@PrepareForTest(ComparativeActivityService.class)
@PowerMockIgnore("javax.management.*")
public class GrouponOrderServiceImplTest {
@Before
public void setUp() throws Exception {
//使用反射的方式 mock protected、 private 方法,但是一般情况下是不应该 mock 这些方法的
PowerMockito.doReturn(false).when(comparativeActivityService, ComparativeActivityService.class.getSuperclass().getDeclaredMethod("inNewSystem",long.class)).withArguments(111L);
//此处是 mock 一个父类的 protected 方法,其他方法类似
}
}
8.使用白盒测试
Whitebox.setInternalState(someService, "someField", new SomeField());
说明:Whitebox.setInternalState(injectObject,"fieldName", fieldObject)
来为一个不能直接使用@Mock 注解来注入的属性注入一个对象
待续
tips
-
打桩失败;在Test层可以debug看见打桩,但是进入被测函数就发现打桩失败了
原因:被测试类有一个final字段,并且使用了构造函数传入了此final字段;
解决:去掉final修饰,将构造函数改为无参构造函数,使用Java注解进行注入
-
verify校验失败:使用eq(obj)校验的时候,一个是引用地址,另一个是实际对象的值
参考:https://stackoverflow.com/questions/25213897/test-failure-message-in-mockito-arguments-are-different-wanted
原因:eq函数并不能区分是引用地址还是引用的对象值
解决办法:将eq函数修改为refEq函数保证校验的都是对象的值
参考链接: https://www.cnblogs.com/Ming8006/p/6297333.html