IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 开发测试 -> mybatis-plus踩坑之批量插入单元测试 -> 正文阅读

[开发测试]mybatis-plus踩坑之批量插入单元测试

背景

?????? mybatis-plus作为mybatis的增强工具,在使用过程中简化开发,大大得提高了工作效率。mybatis-plus提供了一套通用的mapper和service操作,对于单表操作很方便,但是在写单元测试的时候还是存在有很多不同于mybatis的地方。本文介绍本人在开发过程当中遇到的一些坑和自己的理解。

?????? Mock是在测试过程中,对于一些不容易构造的对象,创建一个mock对象来模拟对象的行为。比如说当写单元测试不想调用数据库时,就可以在调用mapper的方法时使用Mock打桩,mock想要返回的结果。

依赖引用

<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-boot-starter</artifactId>
    <version>3.3.1</version>
</dependency>
<dependency>
    <groupId>org.mockito</groupId>
    <artifactId>mockito-core</artifactId>
    <version>2.23.4</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.powermock</groupId>
    <artifactId>powermock-api-mockito2</artifactId>
    <version>2.0.2</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.powermock</groupId>
    <artifactId>powermock-module-junit4</artifactId>
    <version>2.0.2</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.powermock</groupId>
    <artifactId>powermock-core</artifactId>
    <version>2.0.2</version>
    <scope>test</scope>
</dependency>

<dependency>
    <groupId>org.powermock</groupId>
    <artifactId>powermock-module-junit4-rule</artifactId>
    <version>2.0.2</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.12</version>
    <scope>test</scope>
</dependency>

Service

@Service
public class TestServiceImpl  extends ServiceImpl<TestMapper, UserInfo> implements TestService {


    @Override
    public boolean insert(UserInfo userInfo) {
        return this.save(userInfo);
    }

    @Override
    public boolean insertList(List<UserInfo> list) {
        return this.saveBatch(list, 1000);
    }
}

单元测试

首先对单个插入进行单元测试,通过分析mybatis-plus自带的ServiceImpl,发现save方法调用的Mapper的insert方法

default boolean save(T entity) {
    return SqlHelper.retBool(this.getBaseMapper().insert(entity));
}

单元测试代码如下:

@RunWith(PowerMockRunner.class)
@SpringBootTest
public class TestServiceImplTest {

    @InjectMocks
    private TestServiceImpl testService;

    @Mock
    private TestMapper testMapper;

    @Test
    public void testInsert() {
        UserInfo userInfo = new UserInfo();
        userInfo.setId(1);
        userInfo.setName("张三");
        //对mapper的insert打桩,返回成功标识1
        PowerMockito.when(testMapper.insert(userInfo)).thenReturn(1);
        Assert.assertTrue(testService.insert(userInfo));
    }

}

单个插入的单元测试就很简单,但是通过分析批量插入的saveBatch方法发现没有通过Mapper,而是直接在service层实现的,这时该在哪个方法上打桩?有没有办法直接在saveBatch方法上打桩?

public boolean saveBatch(Collection<T> entityList, int batchSize) {
    String sqlStatement = this.sqlStatement(SqlMethod.INSERT_ONE);
    return this.executeBatch(entityList, batchSize, (sqlSession, entity) -> {
        sqlSession.insert(sqlStatement, entity);
    });
}
protected <E> boolean executeBatch(Collection<E> list, int batchSize, BiConsumer<SqlSession, E> consumer) {
    Assert.isFalse(batchSize < 1, "batchSize must not be less than one", new Object[0]);
    return !CollectionUtils.isEmpty(list) && this.executeBatch((sqlSession) -> {
        int size = list.size();
        int i = 1;

        for(Iterator var6 = list.iterator(); var6.hasNext(); ++i) {
            E element = var6.next();
            consumer.accept(sqlSession, element);
            if (i % batchSize == 0 || i == size) {
                sqlSession.flushStatements();
            }
        }

    });
}

首先,尝试直接在Mock对象TestServiceImpl的saveBatch方法上打桩,结果直接报错,无法运行

@Test
public void testInsertList() {
    PowerMockito.when(testService.saveBatch(Mockito.anyList())).thenReturn(true);
    List<UserInfo> list = new ArrayList<>();
    UserInfo userInfo = new UserInfo();
    userInfo.setId(1);
    userInfo.setName("张三");
    list.add(userInfo);
    Assert.assertTrue(testService.insertList(list));
}

在这里插入图片描述

Mockito.spy()可以在真实对象上创建间谍(类似于浅克隆),尝试在创建的间谍对象上打桩

 @Test
 public void testInsertList() {
 	 //创建spy间谍对象
     TestService spy = Mockito.spy(testService);
     PowerMockito.doReturn(true).when(spy).saveBatch(Mockito.anyList());
     List<UserInfo> list = new ArrayList<>();
     UserInfo userInfo = new UserInfo();
     userInfo.setId(1);
     userInfo.setName("张三");
     list.add(userInfo);
     //特别注意,spy对象和testService对象是两个不同的对象,一定要调用spy对象的insertList方法
     Assert.assertTrue(spy.insertList(list));
 }

测试结果通过,完美解决Mybatis-plus批量插入的单元测试
在这里插入图片描述

  开发测试 最新文章
pytest系列——allure之生成测试报告(Wind
某大厂软件测试岗一面笔试题+二面问答题面试
iperf 学习笔记
关于Python中使用selenium八大定位方法
【软件测试】为什么提升不了?8年测试总结再
软件测试复习
PHP笔记-Smarty模板引擎的使用
C++Test使用入门
【Java】单元测试
Net core 3.x 获取客户端地址
上一篇文章      下一篇文章      查看所有文章
加:2021-12-23 16:01:58  更:2021-12-23 16:02:02 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/18 4:27:47-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码