前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Java单元测试Mock工具Mockito介绍

Java单元测试Mock工具Mockito介绍

作者头像
心平气和
发布2021-10-14 15:23:08
3.3K0
发布2021-10-14 15:23:08
举报
文章被收录于专栏:程序员升级之路

一、什么是Mock&为什么要Mock

Mock就是在测试过程中对于那些不容易构建的依赖进行模拟,以保证系统的测试流程可以正常运行,即生成一个和实际使用场景不一样的对象;

为什么需要Mock呢?

1、在测试环境中构建一些依赖的成本比较高

如一些硬件的操作,像串口和USB输入;

还有一些第三方依赖,像支付系统要调用很多外部支付网关,如果直接调用生产环境的网关就会产生脏数据的问题;

2、分而测之

以上面的例子来说,生产环境中就是要从硬件输入,那这块是不是不测试呢?肯定是要测试的,不过分开来测,一部分测试软件上的流程,即从硬件输入后系统的处理流程是否正常,在一些异常下数据是否准确;而硬件输入的测试可以由单独的团队测试,这样就可以并行测试提高效率。

二、Mockito介绍

Mockito是一款优秀的Mock工具,以下是其相关的介绍:

Mockito源码:

https://github.com/mockito/mockito

Mockito2.x新特性介绍:

https://github.com/mockito/mockito/wiki/What%27s-new-in-Mockito-2

接下来介绍Mockito的具体使用:

1、引入依赖:

代码语言:javascript
复制
<dependency>
    <groupId>org.mockito</groupId>
    <artifactId>mockito-core</artifactId>
    <version>3.7.7</version>
    <scope>test</scope>
</dependency>

2、模拟对象

具体的方式有2种:调用spy方法,或加Spy注解;

先讲下我们的范例代码,假设我们有个简单的PostService,用来操作帖子的:

代码语言:javascript
复制
public class PostService {
    @Resource
    private UserService userService;

    /**
    * 添加帖子
     * @return
     */
   public void addPost(Post post){
       User user = userService.findUser(post.getUserId());
       if (user.isDisabled()){
           //用户被禁用
       }
   }
 }

上面是个简单的例子,在添加帖子的时候需要调用用户服务来查询用户信息,这里不讨论代码组织是否合理,是否用到了DDD,只是一个例子说明如何使用Mockito;

先看看spy方法如何Mock:

代码语言:javascript
复制
import static org.mockito.Mockito.spy;

public class PostServiceTest extends TestMain {
    @Autowired
    private UserService userService;
    
    @Test
    public void testAddPost() throws Exception {
        UserService mockUserService = spy(userService);
        Post post = new Post();
        post.setTitle("test");
        post.setAutor("Edward");
        post.setUserId(123);
        Mockito.when(mockUserService .findUser(
        Mockito.anyInt()).thenReturn(
            new User(123, "edward", 1)
            //用户ID,用户名,用户状态1:正常,0:禁用
        ));
    }
}

Spy注解

代码语言:javascript
复制
public class PostServiceTest extends TestMain {
   @Autowired
   @Spy
   private UserService userService;
    
   private AutoCloseable autoCloseable;
   
    @BeforeClass
    public void initMock() {
        autoCloseable = MockitoAnnotations.openMocks(this);
    }
    @AfterClass
    public void close() throws Exception {
        autoCloseable.close();
    }
    
 }

注意这里要调用MockitoAnnotations.openMocks,不然会报错;

可以看到上面拦截方法调用的语法是Mockito.when(..).thenReturn

when传方法,thenReturn传递要返回的结果,如果when要带参数,一般是这样的格式, Mockito.anyInt(),Mockito定义了很多常用类型,可以根据自己需要选择;

3、模拟静态方法

如果要用Mockito模拟静态方法,一是要保证Mockito包版本在3.4.0以上,二是需要额外加mockito-inline依赖,如下:

代码语言:javascript
复制
<dependency>
    <groupId>org.mockito</groupId>
    <artifactId>mockito-inline</artifactId>
    <version>3.7.7</version>
    <scope>test</scope>
</dependency>

加好依赖后,通过 Mockito.mockStatic 来模拟静态方法。

代码语言:javascript
复制


@Test
public void testStaticMethod() {
    LocalDate dummy = LocalDate.of(2021, 10, 4);
    try (MockedStatic<LocalDate> theMock = Mockito.mockStatic(LocalDate.class)) {
        theMock.when(LocalDate::now).thenReturn(dummy);

        LocalDate now = LocalDate.now();
        System.out.println(now);
        Assert.assertEquals(2021, now.getYear());
    }

}

这里要注意dummy一定要放在mockStatic前面,因为后面一旦Mock了,所有静态方法都被Mock掉,of静态方法没有设置返回值会报错的。

聊聊DDD的分层架构

Codis源码分析之Slots迁移篇

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-10-04,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 程序员升级之路 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档