Mockito

Mockito的主要作用:

Mockito主要是为了解除类之间的依赖,隔离一些无法执行的逻辑,例如:

依赖注入隔离Native方法:

public class NativeModel {
    public native boolean nativeMethod();
}

public class ModelTest {
    NativeModel model;
    
    @Before
    public void setUp() throws Exception {
        model = new Model();
    }

    @Test
    public void testNativeMethod() throws Exception {
        Assert.assertTrue(model.nativeMethod());
    }
}

直接运行会抛出UnsatisfiedLinkError,因为Junit无法调用Native方法
所以要用mock进行依赖隔离,正确写法如下:

public class ModelTest {
    NativeModel model;

    @Before
    public void setUp() throws Exception {
        model = mock(NativeModel .class);
    }

    @Test
    public void testNativeMethod() throws Exception {
        when(model.nativeMethod()).thenReturn(true);
        Assert.assertTrue(model.nativeMethod());
    }
}
依赖:
dependencies {
   testImplementation "org.mockito:mockito-core:2.11.0"
}
Mock的几种方式:

1.普通的Mock方式:

public class Test {
    @Test
    public void test() {
        Model model = Mockito.mock(Mode.class); 	//这里Mode可以是任何一个类或接口
       	Assert.assertNotNull(model);
    }
}

2.通过mock注解:

public class MockitoAnnotationsTest {
    @Mock 
    Model model;

    @Before
    public void setup(){
        MockitoAnnotations.initMocks(this);
    }

    @Test
    public void testIsNotNull(){
        assertNotNull(model);
    }
}

3.使用RunWith注解:

@RunWith(MockitoJUnitRunner.class)
public class test {
    @Mock
    Model model;
    
    @Test
    public void test(){
        Assert.assertNotNull(model);
    }
}

4.通过Rule:

public class test {
    @Mock
    Model model;

	//MockitoJUnit的evaluate方法里在开始测试前执行了MockitoAnnotations.initMocks()方法,所以无需手动执行了
    @Rule
    public MockitoRule mockitoRule = MockitoJUnit.rule();

    @Test
    public void test(){
        Assert.assertNotNull(model);
    }
}
Spy

和mock方法类似的还有spy方法,它的创建也与mock类似,用spy替换mock就可以
它与mock方法的区别在于spy使用了对象的真实逻辑,可以理解为spy就是new了一个对象
当然spy得到的对象也可以通过打桩替换掉真实逻辑,方便测试

打桩方法:

打桩就是屏蔽类型原本的方法,而使用自定义的简单逻辑代替实际逻辑

thenReturn(T value) 				设置要返回的值
thenThrow(Throwable… throwables) 	设置要抛出的异常
thenAnswer(Answer<?> answer) 		对结果进行拦截
doReturn(Object toBeReturned) 		提前设置要返回的值
doThrow(Throwable… toBeThrown) 		提前设置要抛出的异常
doAnswer(Answer answer) 			提前对结果进行拦截
doCallRealMethod() 					调用某一个方法的真实实现
doNothing() 						设置void方法什么也不做
@Test
public void test() {
    Mockito.when(Model.isEmpty("")).thenReturn(true);
    Mockito.when(Model.isEmpty(null)).thenThrow(new NullPointerException());
    Mockito.when(Model.isEmpty(null)).thenAnswer(answer-> {
        //获得所有参数
        Object[] args = answer.getArguments();
        //这里可以增加一些逻辑
        system.out.print("do something");
        //然后返回打桩的方法相同类型的值
        return false;
    });
}

spy对象的创建和mock对象是类似的,使用了spy就无需像mock一样打桩了

验证方法:
after(long millis) 							在给定的时间后进行验证
timeout(long millis) 						验证方法执行是否超时
atLeast(int minNumberOfInvocations) 		至少进行n次验证
atMost(int maxNumberOfInvocations) 			至多进行n次验证
description(String description) 			验证失败时输出的内容
times(int wantedNumberOfInvocations) 		验证调用方法的次数
never() 									验证交互没有发生,相当于times(0)
only() 										验证方法只被调用一次,相当于times(1)

例:

 Mockito.verify(model, Mockito.atLeast(2)).isEmpty("");			//验证model的isEmpty("")方法至少执行了两次
 Mockito.verify(model, Mockito.atMost(2)).isEmpty("");			//验证model的isEmpty("")方法至少执行了两次
 Mockito.verify(model, Mockito.times(2)).isEmpty("");			//验证model的isEmpty("")方法执行了两次
 Mockito.verify(model, Mockito.timeout(1000).times(2)).getAge();	//验证model的isEmpty("")方法在1s内执行了两次
参数匹配器:

作用是区分参数的类型,方便依据不同的参数类型返回不同的值

anyObject() 							//匹配任何对象
any(Class<T> type) 						//与anyObject()一样
any() 									//与anyObject()一样
anyBoolean() 							//匹配任何boolean和非空Boolean
anyByte() 								//匹配任何byte和非空Byte
anyCollection() 						//匹配任何非空Collection
anyDouble() 							//匹配任何double和非空Double
anyFloat() 								//匹配任何float和非空Float
anyInt() 								//匹配任何int和非空Integer
anyList() 								//匹配任何非空List
anyLong() 								//匹配任何long和非空Long
anyMap() 								//匹配任何非空Map
anyString() 							//匹配任何非空String
contains(String substring) 				//参数包含给定的substring字符串
argThat(ArgumentMatcher <T> matcher) 	//创建自定义的参数匹配模式
Mockito.when(model.isEmpty(any(String.class))).thenReturn(true);	//对任何输入数据都返回true;
Mockito.when(model.isEmpty(anyString())).thenReturn(true);			//同上
//自定义筛选条件,满足条件的就会返回true;
Mockito.when(model.isEmpty(argThat(arg -> arg != null))).thenReturn(true);	
自动注入:
public interface Person {
    String getName();
}

public class Model {
    Person person;
    public String getName() {
        return person.getName();
    }
}

测试类:

public class Test {
    @InjectMocks
    Model model;
    @Mock
    Person person;
    @Rule
    public MockitoRule mockitoRule = MockitoJUnit.rule();

    @Test
    public void test() {
        Mockito.when(person.getName()).thenReturn("Tom");
        //这里会自动将person注入model,这里实际返回的是person的getName方法
        Assert.assertEquals(model.getName(), "Tom");
    }
}
Mockito框架不足:

Mockito框架不支持mock匿名类、final类、static方法、private方法,PowerMock解决了这个问题

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值