单元测试进阶-使用 Mockito 进行测试

官方文档传送门:mockito 官网

一、必要的说明

先来谈谈为什么要用 Mockito 。如果某接口的功能是:根据一定逻辑往数据库里添加一条记录的用户注册,那么这个操作可以是认为有副作用的,除非你使用该接口后又进行回滚。

@Rollback
@Transactional

显然 Spring 框架提供的上述注解可以很好的完成这样的操作,但是如果当登录接口对注册信息有依赖的话,那么直接回滚会带来很多麻烦。

那么有没有既不影响其他模块的使用又不产生副作用的方法呢?那么就该请出我们的 Mockito 了。用最通俗的“人话”讲,Mockito 是一个能生成假对象来配合测试用的工具。你可以给这个假对象设置一系列应答策略,例如:传入 “请求值”的字符串就 return“返回值”的结果。

另:Mockito 可以很好地与 SpringBootTest、Junit……整合,下文样例也是基于该环境

二、创建 mock 对象

创建 mock 对象在 Spring 环境下主要涉及下列两个注解

    @Mock
    // 被该注解标记的对象既是 Mock 对象

    @InjectMocks
    // 被该注解标记的对象既是 Mock 对象,不同的是,若该对象内如果包含了被 @Mock 标记的对象,那么其内部的对象也会被替换成 Mock 对象

三、配置 Mock 对象应答策略

提示下,下面涉及的方法主要出自这个包
import static org.mockito.BDDMockito.*;

1.正常返回

@Before
public void init(){
User u1=new User("张三");
User u2=new User("李四");
given(userService.addUser(any(User.class))).willReturn(u1,u2);
// 实际含义:在用任意一个 User 对象作参数的情况下,userServuce 第一次调用 addUser()方法时,addUser() 方法返回 u1 对象(张三),第二次调用返回 u2 对象(李四) PS:每个 @Test 方法内都单独计数,多个 @Test 方法时互相不影响不会累加次数
// any(User.class) 的含义是传入任何 User 对象均匹配上willReturn 逻辑,否则返回 null
// anyString() 与 any(String.calss) 等效,但是目前可以确定的是,如果你想 Mock 的方法参数包含  Class tClass 参数,那么就行不通了,因为 Matchers 里并没有返回 Class 对象的方法。

given(userService.delUser("U00000001").willReturn(true);
given(userService.delUser("U00000002").willReturn(false);
// 与上方不同,这里是指定的具体参数 u1、u2,含义是,delUser方法传入 "U00000001" 参数则返回布尔值 true、传入 "U00000002" 参数则返回布尔值 false 
}

2.抛出异常

@Before
public void init(){
given(userService.delUser(anyString()).willThrow(new Exception());
// 此处含义:delUser 传入任何字符串时抛出 Exception 类型的异常,any()、每次访问抛出不同异常使用方法与 1.正常返回 一致,故不再赘述
}

3.什么都不写

@Before
public void init(){

}

那么所有没声明应答策略的方法 将正确运行,不会抛出异常,返回值会默认为 null

四、进行测试

在 三、配置 Mock 对象应答策略 已完成的基础上

@SpringBootTest
@RunWith(SpringRunner.class)
public class UserServiceTest{
    @Mock
    UserMapper userMapper;
    @InjectMocks
    UserServic userService;// 其内部存在 UserMapper 对象

    @Before
    public void init(){
    //配置 Mock 对象应答策略 ……
    }


    @Test
    public void test() throw Exception{
    Boolean result= userService.delByUid("U00000001");
    verify(userService, times(1)).delByUid(anyString());// delByUid() 是否调用了1次
    assertEquals(true,result);// delByUid 的返回值是否是 true

    }
}

猜你喜欢

转载自blog.csdn.net/u014430366/article/details/77449066