如何用mockito+junit测试代码

Mockito 是一个流行的 Java 模拟测试框架,用于创建和管理测试中的模拟对象(mock objects)。它可以帮助开发者编写干净、可维护的单元测试,特别是在需要隔离被测组件与其他依赖项时。

目录

核心概念

[1. 模拟对象(Mock Objects)](#1. 模拟对象(Mock Objects))

[2. 打桩(Stubbing)](#2. 打桩(Stubbing))

[3. 验证(Verification)](#3. 验证(Verification))

[1. 测试准备](#1. 测试准备)

[2. 模拟依赖(Mock)](#2. 模拟依赖(Mock))

[3. 执行测试](#3. 执行测试)

[4. 验证结果](#4. 验证结果)

[5. 验证收藏数增加](#5. 验证收藏数增加)

总结


核心概念

1. 模拟对象(Mock Objects)

模拟对象是真实对象的替代品,用于在测试中模拟真实对象的行为,而不需要实际调用真实对象。

2. 打桩(Stubbing)

定义模拟对象在特定条件下的行为,即当调用某个方法时返回什么值或抛出什么异常。

3. 验证(Verification)

验证模拟对象的特定方法是否被调用,以及调用的次数和参数是否符合预期。

下面进行实际操作

等待测试的源码:

java 复制代码
    @Override
    public JSONReturn save(Collect collect) {
        Collect exist = collectMapper.selectExist(collect.getUserId(),collect.getForumId());
        if(exist != null){
            return JSONReturn.failed("操作失败,您已收藏该帖子!");
        }
        Date date = new Date();
        collect.setCreateTime(date);
        collect.setUpdateTime(date);
        collectMapper.insert(collect);
//        //收藏+1
        Forum forum = forumMapper.selectByPrimaryKey(collect.getForumId());
        forum.setCollectNum(forum.getCollectNum() + 1);
        forumMapper.updateByPrimaryKeySelective(forum);
        return JSONReturn.success("收藏成功!");
    }

以下下是mock的代码

java 复制代码
    @Test
    void save_shouldReturnSuccess_whenCollectNotExists() {
        Collect collect = new Collect();
        collect.setUserId(2);
        collect.setForumId(9);
        
        when(collectMapper.selectExist(2, 9)).thenReturn(null); 

        Forum forum = new Forum();
        forum.setCollectNum(0);
        when(forumMapper.selectByPrimaryKey(9)).thenReturn(forum);
        
        JSONReturn result = collectService.save(collect);
        
        assertEquals("收藏成功!", result.getMsg());  // Should return success message
        verify(collectMapper, times(1)).selectExist(2, 9);
        verify(collectMapper, times(1)).insert(collect);
        verify(forumMapper, times(1)).updateByPrimaryKeySelective(any(Forum.class));

        ArgumentCaptor<Forum> forumCaptor = ArgumentCaptor.forClass(Forum.class);
        verify(forumMapper).updateByPrimaryKeySelective(forumCaptor.capture());
        Integer collectNum = forumCaptor.getValue().getCollectNum();
        assertEquals(new Integer(1), collectNum);
    }

这是一个单元测试方法,测试当收藏记录不存在时成功保存收藏的功能。下面是对代码的逐步解释:

1. 测试准备

java 复制代码
Collect collect = new Collect();
collect.setUserId(2);
collect.setForumId(9);

创建一个新的收藏对象,设置用户ID为2,论坛ID为9。

2. 模拟依赖(Mock)

java 复制代码
when(collectMapper.selectExist(2, 9)).thenReturn(null);

模拟collectMapper.selectExist(2, 9)方法调用,返回null表示该收藏记录不存在。

java 复制代码
Forum forum = new Forum();
forum.setCollectNum(0);
when(forumMapper.selectByPrimaryKey(9)).thenReturn(forum);

创建一个论坛对象,设置收藏数为0,并模拟forumMapper.selectByPrimaryKey(9)返回这个论坛对象。

3. 执行测试

java 复制代码
JSONReturn result = collectService.save(collect);

调用被测试的collectService.save()方法。

4. 验证结果

java 复制代码
assertEquals("收藏成功!", result.getMsg());

验证返回的消息是"收藏成功!"。

java 复制代码
verify(collectMapper, times(1)).selectExist(2, 9);
verify(collectMapper, times(1)).insert(collect);

验证:

  • selectExist方法被调用了一次

  • insert方法被调用了一次

java 复制代码
verify(forumMapper, times(1)).updateByPrimaryKeySelective(any(Forum.class));

验证updateByPrimaryKeySelective方法被调用了一次。

5. 验证收藏数增加

java 复制代码
ArgumentCaptor<Forum> forumCaptor = ArgumentCaptor.forClass(Forum.class);
verify(forumMapper).updateByPrimaryKeySelective(forumCaptor.capture());
Integer collectNum = forumCaptor.getValue().getCollectNum();
assertEquals(new Integer(1), collectNum);

使用ArgumentCaptor捕获传递给updateByPrimaryKeySelective的Forum对象,验证其收藏数从0增加到了1。

总结

这个测试验证了当用户收藏一个尚未收藏的论坛时:

  1. 系统会检查该收藏记录是否存在

  2. 如果不存在则创建新收藏记录

  3. 更新论坛的收藏数(+1)

  4. 返回成功消息

测试覆盖了收藏服务的主要逻辑路径,确保在收藏记录不存在时的正确行为。

相关推荐
Best-Wishes1 天前
科来网络分析系统(技术交流版)使用说明书
开发语言·junit·php
贾宝玉的玉宝贾1 天前
FreeSWITCH 简单图形化界面 70 - 监听/密语的lua脚本
开发语言·junit·lua·voip·freeswitch·sip·ippbx
企业数字化笔记2 天前
多租户系统从哪里开始设计?租户身份、数据隔离、权限与套餐的整体方案
java·spring boot·后端·junit
众链网络6 天前
大客流票务系统怎么防超卖:库存并发、候补队列与幂等设计的工程取舍
junit·架构
深念Y9 天前
rime-雾凇拼音-配置记录
linux·junit·软件·拼音·kde
白山编程大哥12 天前
Lua 中使用 C 语言的用户自定义类型——userdata
c语言·junit·lua
行者游学15 天前
Kong 插件,解决2.5.1不支持原生暴露url
junit·kong
写后端的胖头鱼1 个月前
一文学会单元测试之----Junit
junit·单元测试
Java小白笔记1 个月前
Java 单元测试怎么写:JUnit 5、Mockito 与 Spring Boot 方法级实战
java·junit·单元测试
盟道科技1 个月前
Redis+Lua 实现滑动窗口限流:从固定窗口踩坑到生产可用的完整方案
redis·junit·lua