Mrli
别装作很努力,
因为结局不会陪你演戏。
Contacts:
QQ博客园

Springboot-Kotlin-Mockito

2022/01/03 开发笔记
Word count: 1,373 | Reading time: 6min

初识 Mockito 这个测试框架后,我们要使用 Mock 的属性创建一个被测试类实例时,大概会下面这么纯手工来打造。

手工过程见: https://www.jianshu.com/p/bb705a56f620

如果所有的 Mock 对象全部通过手工来创建,那就不容易体现出 Mockito 的优越性出来。因此对于被测试对象的创建,Mock 属性的注入应该让 @Mock 和 @InjectMocks这两个注解大显身手了。

Mockito能力

  • @Mock:对函数的调用均执行mock(即虚假函数),不执行真正部分。
  • @Spy:对函数的调用均执行真正部分。
  • @InjectMocks:创建一个实例,其余用@Mock(或@Spy)注解创建的mock将被注入到用该实例中。

@Autowird 方式是基于Springboot框架启动的自动注入。在单元测试中,如果没有启动 spring 框架,此时就需要通过 @ InjectMocks完成依赖注入: @InjectMocks会将带有@Spy 和@Mock 注解的对象尝试注入到被 测试的目标类中。记住下面这两句话即可:

  • Usually when you are unit testing, you shouldn’t initialize Spring context. So remove Autowiring.
  • Usually when you do integration testing, you should use real dependencies. So remove mocking.

这边也解释了,@RunWith(MockitoJUnitRunner::class)的含义,其实是给下面Mockito注入的成员提供一个运行环境,为什么不直接使用@SpringBootTest的原因主要还是启动太多,运行太重的考虑。那什么时候得用@SpringBootTest呢?——最简单的情况,即要注入controller又要注入service,同时需要@mock存储层的repository,由于controller和service都需要标注@InjectMocks, 但InjectMocks字段是无法注入其他InjectMocks字段的。所以我们可以考虑使用Spring来做容器管理。

@Mock@MockBean区别

MockBean的介绍:

1
2
3
4
在做单元测试时,如果想要 mock UserRepository 的逻辑,只需要声明一个变量并在上面加上 @MockBean 的注释即可,
之后使用 when().thenReturn() 来设定 mock UserRepository 的行为。
在运行时 SpringBoot 会扫描到你注释的 mock ,并自动装配到被测试的 controller 里面。
这也是和 @Mock 注释不同的地方,后者只能生成一个 Mock 类,但是并不能自动装配到其它类里面。

因此,@Mock方便来做单元测试,@MockBean大多用来做有依赖关系的集成测试

vertify

验证行为是否发生

verify方法用于验证 mock bean 的方法调用,要求必须是mock对象

  • Mockito . *verify* (mockBean ).someMethod();表示:someMethod方法调用了一次,相当于times(1)
  • Mockito . *verify* (mock Bean, Mockito.times(n) ).someMethod();表示:someMethod方法调用了n次
  • Mockito . *verify* (mock Bean, Mockito.never() ).someMethod();表示:someMethod方法未执行
  • Mockito . *verify* (mock Bean, Mockito. atLeastOnce() ).someMethod();表示:someMethod方法至少执行过一次,相当于atLeast(1)

需要注意的:Mockito.*verify* (mock Bean, Mockito.only() ).someMethod();表示: 仅有someMethod方法执行,且只有一次,不能有其他方法执行

more: https://www.jianshu.com/p/0e6a868b9da0

常用的 Mockito 方法:

Mockito的使用,一般有以下几种组合:参考链接

do/when:包括doThrow(…).when(…)/doReturn(…).when(…)/doAnswer(…).when(…)
given/will:包括given(…).willReturn(…)/given(…).willAnswer(…)
when/then: 包括when(…).thenReturn(…)/when(…).thenAnswer(…)

方法名 描述
Mockito.mock(classToMock) 模拟对象
Mockito.verify(mock) 验证行为是否发生
Mockito.when(methodCall).thenReturn(value1).thenReturn(value2) 触发时第一次返回value1,第n次都返回value2
Mockito.doThrow(toBeThrown).when(mock).[method] 模拟抛出异常。
Mockito.mock(classToMock,defaultAnswer) 使用默认Answer模拟对象
Mockito.when(methodCall).thenReturn(value) 参数匹配
Mockito.doReturn(toBeReturned).when(mock).[method] 参数匹配(直接执行不判断)
Mockito.when(methodCall).thenAnswer(answer)) 预期回调接口生成期望值
Mockito.doAnswer(answer).when(methodCall).[method] 预期回调接口生成期望值(直接执行不判断)
Mockito.spy(Object) 用spy监控真实对象,设置真实对象行为
Mockito.doNothing().when(mock).[method] 不做任何返回
Mockito.doCallRealMethod().when(mock).[method] //等价于Mockito.when(mock.[method]).thenCallRealMethod(); 调用真实的方法
reset(mock) 重置mock

Matchers

  • 匹配任意参数

  • Mockito.anyInt() 任何 int 值 ;

  • Mockito.anyLong() 任何 long 值 ;

  • Mockito.anyString() 任何 String 值 ;

  • Mockito.any(XXX.class) 任何 XXX 类型的值 等等。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@Test
public void with_unspecified_arguments(){
List list = Mockito.mock(List.class);
//匹配任意参数
Mockito.when(list.get(Mockito.anyInt())).thenReturn(1);
Mockito.when(list.contains(Mockito.argThat(new IsValid()))).thenReturn(true);
Assert.assertEquals(1,list.get(1));
Assert.assertEquals(1,list.get(999));
Assert.assertTrue(list.contains(1));
Assert.assertTrue(!list.contains(3));
}
class IsValid extends ArgumentMatcher<List>{
@Override
public boolean matches(Object obj) {
return obj.equals(1) || obj.equals(2);
}
}

More:

函数名 匹配类型
any() 所有对象类型
anyInt() 基本类型 int、非 null 的 Integer 类型
anyChar() 基本类型 char、非 null 的 Character 类型
anyShort() 基本类型 short、非 null 的 Short 类型
anyBoolean() 基本类型 boolean、非 null 的 Boolean 类型
anyDouble() 基本类型 double、非 null 的 Double 类型
anyFloat() 基本类型 float、非 null 的 Float 类型
anyLong() 基本类型 long、非 null 的 Long 类型
anyByte() 基本类型 byte、非 null 的 Byte 类型
anyString() String 类型(不能是 null)
anyList() List 类型(不能是 null)
anyMap() Map<K, V>类型(不能是 null)

附录

Junit中的基本注解:

@Test:使用该注解标注的public void方法会表示为一个测试方法;
@BeforeClass:表示在类中的任意public static void方法执行之前执行;
@AfterClass:表示在类中的任意public static void方法之后执行;
@Before:表示在任意使用@Test注解标注的public void方法执行之前执行;
@After:表示在任意使用@Test注解标注的public void方法执行之后执行;

demo:

Author: Mrli

Link: https://nymrli.top/2022/01/03/Springboot-Kotlin-Mockito/

Copyright: All articles in this blog are licensed under CC BY-NC-SA 3.0 unless stating additionally.

< PreviousPost
语义化的版本控制
NextPost >
理解SpringBoot注解s
CATALOG
  1. 1. Mockito能力
  2. 2. @Mock和@MockBean区别
  3. 3. vertify
  4. 4. 常用的 Mockito 方法:
  5. 5. Matchers
  • 附录
    1. 1. Junit中的基本注解: