2024年最新Mock 模拟测试简介及 Mockito 使用入门,2024年上半年最接地气的C C++面经

img
img

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!


Mockito

介绍

Mockito 是一个简单的流行的 Mock 框架。它能够帮我们创建 Mock 对象,保持单元测试的独立性。

使用它只需要在 Maven 中添加依赖即可。

<!-- https://mvnrepository.com/artifact/org.mockito/mockito-all -->
    <dependency>
        <groupId>org.mockito</groupId>
        <artifactId>mockito-all</artifactId>
        <version>2.0.2-beta</version>
    </dependency>

创建 Mock 对象

通过方法创建
class CreateMock {
	@Before
	public void setup() {
		mockUserDao = mock(UserDao.class);  
        userService = new UserServiceImpl();  
        userService.setUserDao(mockUserDao);  
	}
}

通过注解创建
class CreateMock {
	@Mock
	UserDao mockUserDao;
	
	@InjectMocks  
    private UserServiceImpl userService;  

	@Before  
    public void setUp() {  
	    //初始化对象的注解 
        MockitoAnnotations.initMocks(this);  
    }  
}


一个简单的例子:

package Mockito;

import org.junit.Assert;
import org.junit.Test;
import java.util.List;

import static org.mockito.Mockito.*;

public class MyTest {
    @Test
    public void myTest() {
	    /\* 创建 Mock 对象 \*/
        List list = mock(List.class);
		/\* 设置预期,当调用 get(0) 方法时返回 "111" \*/
        when(list.get(0)).thenReturn("111");

        Assert.assertEquals("asd", 1, 1);
        /\* 设置后返回期望的结果 \*/
        System.out.println(list.get(0));
        /\* 没有设置则返回 null \*/
        System.out.println(list.get(1));

        /\* 对 Mock 对象设置无效 \*/
        list.add("12");
        list.add("123");
        /\* 返回之前设置的结果 \*/
        System.out.println(list.get(0));
        /\* 返回 null \*/
        System.out.println(list.get(1));
        /\* size 大小为 0 \*/
        System.out.println(list.size());

        /\* 验证操作,验证 get(0) 调用了 2 次 \*/
        verify(list, times(2)).get(0);

		/\* 验证返回结果 \*/
        String ret = (String)list.get(0);
        Assert.assertEquals(ret, "111");
    }
}

从上面代码能看出一般使用的步骤:

设置方法预期返回

通过 when(list.get(0)).thenReturn(“111”); 来设置当调用 list.get(0) 时返回 “111”,该方法就是 Stub,替换我们实际的操作。

验证方法调用

该方法验证 get(0) 方法调用的次数 verify(list, times(2)).get(0);,还可以设置是否调用过,调用时间等等。

验证返回值

Assert.assertEquals(ret, “111”); 方法验证 Mock 对象方法调用后的返回值是否达到预期。


Mockito 使用

设置 Mock 对象期望和返回值

/\* 表示第一次调用 someMethod() 返回 value1 第二次调用返回 value2 \*/
when(mock.someMethod()).thenReturn(value1).thenReturn(value2);  
when(mock.someMethod()).thenReturn(value1, value2);  
/\* 也可以设置两次 \*/
when(mock.someMethod()).thenReturn(value1);
when(mock.someMethod()).thenReturn(value2);

另外一种写法 doReturn()

/\* 表示第一次调用 someMethod() 返回 value1 第二次调用返回 value2 \*/
doReturn(value1).doReturn(value2).when(mock).someMethod();  
/\* 若返回 void,则设置为 doNothing() \*/
doNothing().when(mock).someMethod();

对方法设定返回异常

/\* 当调用 someMethod() 方法时会抛出异常 \*/
when(mock.someMethod()).thenThrow(new RuntimeException());
/\* 对 void 方法设定 \*/  
doThrow(new RuntimeException()).when(mock).someMethod();  

参数匹配器

我们不一定要固定 Stub 调用时的参数,如 get(0)。可以通过参数匹配器来调用。

when(list.get(anyInt())).thenReturn("hello");


Mock 对象的行为验证

package Mockito;

import org.mockito.ArgumentCaptor;
import org.mockito.InOrder;
import org.testng.annotations.Test;

import java.util.List;
import static org.mockito.Mockito.*;

/\*\*
 \* Created by andy.wwh on 2016/7/18.
 \*/
public class Behavior {
    @Test
    public void behaviorCheck() {
        List mock1 = mock(List.class);
        List mock2 = mock(List.class);

        /\* 设置预期 \*/
        when(mock1.get(0)).thenReturn("hello world");
        when(mock1.get(1)).thenReturn("hello world");
        when(mock2.get(0)).thenReturn("hello world");
        mock1.get(0);

        /\* 验证方法调用一次 \*/
        verify(mock1).get(0);
        mock1.get(0);
        /\* 验证方法调用两次 \*/
        verify(mock1, times(2)).get(0);
        /\* 验证方法从未被调用过 \*/
        verify(mock2, never()).get(0);
        /\* 验证方法 100 毫秒内调用两次 \*/
        verify(mock1, timeout(100).times(2)).get(anyInt());

        /\* 设置方法调用顺序 \*/
        InOrder inOrder = inOrder(mock1, mock2);
        inOrder.verify(mock1, times(2)).get(0);
        inOrder.verify(mock2, never()).get(1);

        /\* 查询是否存在被调用,但未被 verify 验证的方法 \*/
        verifyNoMoreInteractions(mock1, mock2);
        /\* 验证 Mock 对象是否没有交发生 \*/
        verifyZeroInteractions(mock1, mock2);

        /\* 参数捕获器 \*/
        ArgumentCaptor<Integer> argumentCaptor = ArgumentCaptor.forClass(Integer.class);
        verify(mock1, times(2)).get(argumentCaptor.capture());
        System.out.println("argument:" + argumentCaptor.getValue());
    }
}

验证调用次数

verify(mock1, timeout(100).times(2)).get(anyInt());

除了代码中的方法,Mockito 还提供了

  • never() 没有被调用,相当于times(0)
  • atLeast(N) 至少被调用N次
  • atLeastOnce() 相当于atLeast(1)
  • atMost(N) 最多被调用N次
超时验证

通过 timeout 我们可以进行验证程序执行时间是否符合规则。

方法调用顺序

Inorder 可以验证方法调用的顺序

verifyNoMoreInteractions 和 verifyZeroInteractions

verifyNoMoreInteractions:查询是否存在被调用,但未被 verify 验证的方法

verifyZeroInteractions:verifyZeroInteractions

ArgumentCaptor 参数捕获器

可在验证时对方法的参数进行捕获,最后验证捕获的参数值。如果方法有多个参数都要捕获验证,那就需要创建多个ArgumentCaptor对象处理。


Spy 对象验证

Mock 操作的全是虚拟对象。即使我们设置了 when(list.get(0)).thenReturn(1),我们调用如 size() 方法返回的还是 0。Mockito 还给我们提供了一种对真实对象操作的方法——Spy

做一个简单的比较:

package Mockito;

import org.testng.annotations.Test;

import java.util.List;

import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

/\*\*
 \* Created by andy.wwh on 2016/7/18.
 \*/
public class MockObject {
    @Test
    public void MockTest() {
        List list = mock(List.class);

        when(list.get(0)).thenReturn("hello world");

        System.out.println(list.get(0));

        System.out.println(list.size());
    }
}

package Mockito;

import org.testng.annotations.Test;

import java.util.LinkedList;
import java.util.List;

import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;

/\*\*
 \* Created by andy.wwh on 2016/7/18.
 \*/
public class MockObject {
    @Test
    public void MockTest() {
	    /\* 创建真实对象 \*/
        List list = new LinkedList();
        List spy = spy(list);

        spy.add("hello");



![img](https://img-blog.csdnimg.cn/img_convert/f9d5177e3c1a27a305b1aa368f4e709e.png)
![img](https://img-blog.csdnimg.cn/img_convert/36b22e105a48fb63dd2ca9c3e38c616c.png)

**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上C C++开发知识点,真正体系化!**

**由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新**

**[如果你需要这些资料,可以戳这里获取](https://bbs.youkuaiyun.com/topics/618668825)**

        List list = new LinkedList();
        List spy = spy(list);

        spy.add("hello");



[外链图片转存中...(img-GFmexqlq-1715660719144)]
[外链图片转存中...(img-E34C1zOj-1715660719144)]

**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上C C++开发知识点,真正体系化!**

**由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新**

**[如果你需要这些资料,可以戳这里获取](https://bbs.youkuaiyun.com/topics/618668825)**

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值