博主信息
Sky
博文
291
粉丝
0
评论
0
访问量
7229
积分:0
P豆:617

单元测试框架 Mockito 注解 – @Mock, @Spy, @Captor, @InjectMocks

2021年10月16日 23:25:05阅读数:12博客 / Sky

这篇 mockito 的教程文章能够帮助你了解更多 mockito 注解,比如 @Mock, @Spy, @Captor, @InjectMocks,来写出更好的单元测试。

1. Mockito 注解

1.1. @Mock

@Mock 注解被往往用来创建以及注入模拟实例。我们会用 mockito 框架创建一个模拟的实例类,而不是去真的创建需要的对象。

@Mock 注解也可以用 var somethingYouWantMock = Mockito.mock(classToMock) 这种函数方式赋值来替代,它们的效果是一样的,而用 @Mock 注解通常能能看起来代码 “整洁” 一点,因为我们不会想用一堆看起来一样的 Mockito.mock 函数在代码里重复得到处都是。

@Mock 注解的优势:

能够快速创建测试所需的对象重复的模拟创建代码很少测试类可读性更好更容易看懂验证报错,因为注解的模拟类直接是类的属性,可以用字段名去赋予含义。

在下面给出的示例中,我们模拟了HashMap类。在实际测试中,我们将模拟实际的应用类。我们在map中放入一个键值对,然后验证,确认方法调用是在模拟的map实例上执行的。

@MockHashMap<String, Integer> mockHashMap;
@Testpublic void saveTest(){
   mockHashMap.put("A", 1);
   
   Mockito.verify(mockHashMap, times(1)).put("A", 1);
   Mockito.verify(mockHashMap, times(0)).get("A");

   assertEquals(0, mockHashMap.size());}

译者补充:mock意思就是造一个假的模拟对象,不会去调用这个真正对象的方法,这个mock对象里的所有行为都是未定义的,属性也不会有值,需要你自己去定义它的行为。比如说,你可以mock一个假的size(), 使其返回100,但实际上并没有真的创建一个 size 为100的 Map)

...
   when(mockHashMap.size())
       .thenReturn(100);
   
   assertEquals(100, mockHashMap.size());...

1.2. @Spy

@Spy注释用于创建一个真实对象并监视这个真实对象。@Spy对象能够调用所监视对象的所有正常方法,同时仍然跟踪每一次交互,就像我们使用mock一样,可以自己定义行为。

可以看到,在下面给的示例中,由于我们向它添加了一个 key-value 键值对,size 变成了 1。我们也能够得到真正的通过键 key 去拿到 value 值的结果。这在 Mock 注解的例子中是不可能的。

译者补充: 因为mock是模拟整个生成一个假对象,spy像是间谍潜伏在真实对象里去篡改行为。

@SpyHashMap<String, Integer> hashMap;
@Testpublic void saveTest(){
   hashMap.put("A", 10);
   
   Mockito.verify(hashMap, times(1)).put("A", 10);
   Mockito.verify(hashMap, times(0)).get("A");
   
   assertEquals(1, hashMap.size());
   assertEquals(new Integer(10), (Integer) hashMap.get("A"));}

@Mock和@Spy的区别

在使用@Mock时,mockito创建了类的一个基础套壳实例,完全用于跟踪与它的全部交互行为。这不是一个真正的对象,并且不维护状态,不存在更改。

当使用@Spy时,mockito创建一个类的真实实例,手游账号交易平台地图可以跟踪与它的每个交互行为,这个真实类能维护类状态的变化。

1.3 @Captor

@Captor注释用于创建ArgumentCaptor实例,该实例用于捕获方法参数值,来用于进一步做断言验证。

注意mockito使用参数类的equals()方法验证参数值是否相同。

@MockHashMap<String, Integer> hashMap;
@CaptorArgumentCaptor<String> keyCaptor;
@CaptorArgumentCaptor<Integer> valueCaptor;
@Testpublic void saveTest() {
   hashMap.put("A", 10);

   Mockito.verify(hashMap).put(keyCaptor.capture(), valueCaptor.capture());

   assertEquals("A", keyCaptor.getValue());
   assertEquals(new Integer(10), valueCaptor.getValue());}

1.4 @InjectMocks

在mockito中,我们需要创建被测试的类对象,然后插入它的依赖项(mock)来完全测试行为。因此,我们要用到 @InjectMocks 注释。

@InjectMocks 标记了一个应该执行注入的字段。Mockito会按照下面优先级通过构造函数注入、setter注入或属性注入,来尝试注入你标识的mock。如果上面三种任何给定的注入策略注入失败了,Mockito不会报错。

版权申明:本博文版权归博主所有,转载请注明地址!如有侵权、违法,请联系admin@php.cn举报处理!

全部评论

文明上网理性发言,请遵守新闻评论服务协议

条评论