一、@Mock和@InjectMocks
@InjectMocks 通常加在被测试对象上。 该对象不会被mock,会创建真实的对象,把其他Mock的对象注入被测试对象上
@Mock 标注的对象对生成一个假的对象
二、Subbing和Assert
对于以下语法请参照例子:
when…thenReturn,when…thenThrow, when…thenAnswer, when…thenCallRealMethod
doReturn, doThrow, doNothing
Assert:assertEquals, assertThrows
@RunWith(MockitoJUnitRunner.class)
public class SubbingTest {
@Mock
private List<String> list;
@Test
public void how_to_use_subbing(){
//return时thenReturn和doReturn功能一样
Mockito.when(list.get(0)).thenReturn("first");
Mockito.doReturn("second").when(list).get(1);
Assert.assertEquals("first", list.get(0));
Assert.assertEquals("second", list.get(1));
//有返回值throw时用thenThrow
Mockito.when(list.get(Mockito.anyInt())).thenThrow(new RuntimeException());
try {
list.get(0);
fail();
}catch (Exception e){
Assert.assertThrows(RuntimeException.class,()->list.get(0));
}
}
@Test
public void how_to_subbing_return_void_method(){
//对无返回值的方法Mock
Mockito.doNothing().when(list).clear();
list.clear();
Mockito.verify(list,Mockito.times(1)).clear();
//无返回值throw时用doThrow
Mockito.doThrow(RuntimeException.class).when(list).clear();
try {
list.clear();
fail();
}catch (Exception e){
Assert.assertThrows(RuntimeException.class,()->list.clear());
}
}
}
thenAnswer: Sets a generic Answer for the method
@Test
public void subbing_with_answer(){
Mockito.when(list.get(Mockito.anyInt())).thenAnswer(new Answer() {
public Integer answer(InvocationOnMock invocation) throws Throwable {
return (Integer) invocation.getArguments()[0]*10;
}
});
Assert.assertEquals(list.get(2),20);
Assert.assertEquals(list.get(88),880);
}
Mock可以通过thenCallRealMethod方法去执行真正的逻辑
@Test
public void subbing_with_real_call(){
TestService service = Mockito.mock(TestService.class);
Mockito.when(service.m1()).thenReturn("MockM1");
Assert.assertEquals("MockM1", service.m1());
Mockito.when(service.m2()).thenCallRealMethod();
Assert.assertEquals("RealM2", service.m2());
}
public class TestService {
public String m1(){
System.out.println("invoke TestService m1 method...");
return "RealM1";
}
public String m2(){
System.out.println("invoke TestService m2 method...");
return "RealM2";
}
}
三、Spy
当一个真正的对象被spy的时候,该对象可以被部分mock
spy和mock是相反功能。
spy:如果不对spy对象的methodA打桩,那么调用spy对象的methodA时,会调用真实方法。
mock:如果不对mock对象的methodA打桩,将doNothing,且返回默认值(null,0,false)。
@RunWith(MockitoJUnitRunner.class)
public class SpyTest {
@Spy
List<String> list = new ArrayList<>();
@Test
public void spyTest(){
list.add("spy1");
list.add("spy2");
Assert.assertEquals("spy1",list.get(0));
Assert.assertEquals("spy2",list.get(1));
Mockito.when(list.isEmpty()).thenReturn(true);
Mockito.doThrow(RuntimeException.class).when(list).clear();
Assert.assertEquals("spy1",list.get(0)); //调用真实的方法
Assert.assertEquals("spy2",list.get(1));//调用真实的方法
Assert.assertTrue(list.isEmpty()); //spy对象的list.isEmpty()被mock了,就返回mock的值
Assert.assertThrows(RuntimeException.class, ()->list.clear());//spy对象的list.isEmpty()被mock了,就返回mock的值
}
}
四、 Matcher的参数
1) isA(),any(): 两者是一样的 用于配置指定类型的对象。以下是官方文档的解释
Matches any object of given type, excluding nulls.
This matcher will perform a type check with the given type, thus excluding values.
any(Class type) is an alias of isA(Class type)
import org.junit.Assert;
import org.junit.Test;
import org.mockito.Mockito;
public class IsAMethodTest {
@Test
public void isATest() {
Foo foo = Mockito.mock(Foo.class);
Mockito.when(foo.fun(Mockito.isA(Parent.class))).thenReturn(100); //需要配置类型为Parent的对象
int cd1 = foo.fun(new Child1());
int cd2 = foo.fun(new Child2());
Assert.assertEquals(cd1, 100); //Child1类型为Parent
Assert.assertEquals(cd2, 100); //Child2类型为Parent
}
class Foo {
int fun(Parent p) {
return p.work();
}
}
interface Parent {
int work();
}
class Child1 implements Parent {
@Override
public int work() {
throw new RuntimeException();
}
}
class Child2 implements Parent {
@Override
public int work() {
throw new RuntimeException();
}
}
}
3) eq() :Object argument that is equal to the given value. 判断传入的参数是否跟指定的值相等
4) WildCard: anyInt(), anyDouble(), anyString(), anyList(), anyCollection()
@RunWith(MockitoJUnitRunner.class)
public class WildCardTest {
@Mock
WDService service;
@Test
public void testwd(){
when(service.methodReturnint(anyInt(),anyString(),anyCollection(),isA(Serializable.class))).thenReturn(10);
int res = service.methodReturnint(1,"qwe", Collections.emptyList(),"Mockito");
Assert.assertEquals(10, res);
}
@Test
public void testMethodReturnVoid(){
doNothing().when(service).methodReturnVoid(anyInt(),anyString(),anyCollection(),isA(Serializable.class));
service.methodReturnVoid(1,"qwe", Collections.emptyList(),"Mockito");
//由于参数没有返回值,所以要判断方法的执行次数来验证
verify(service,times(1)).methodReturnVoid(1, "qwe", Collections.emptyList(),"Mockito");
//任意一个参数使用wildcard时, 其他也要使用wildcard。如果想指定特殊值,就要写在eq()内,否则拨错
verify(service,times(1)).methodReturnVoid(anyInt(), eq("qwe"), anyCollection(), "Mockito");
}
}
class WDService {
public int methodReturnint(int i, String s, Collection c, Serializable b){
throw new RuntimeException();
}
public void methodReturnVoid(int i, String s, Collection c, Serializable b){
throw new RuntimeException();
}
}