首页 > 其他分享 >mybatis单元测试(无需启动容器)

mybatis单元测试(无需启动容器)

时间:2023-07-05 11:14:01浏览次数:38  
标签:容器 mapper import 单元测试 apache Executor mybatis org configuration

一、浅析相关类

参考文档:https://blog.csdn.net/weixin_44778952/article/details/109661125

1 Configuration
MyBatis在启动时会取读取所有配置文件,然后加载到内存中,Configuration类就是承载整个配置的类。
SqlSessionFactoryBuilder调用build方法创建SqlSessionFactory,而SqlSessionFactory需要Configuration配置中心提供创建的条件,在build方法中XMLConfigBuilder 将xml文件流进行初始化并parse返回Configuration,返回之前需要通过parseConfiguration来真正为Configuration设置信息,XPathParser负责将节点下的信息转换成XNode对象方便访问。

2 Executor
Executor是跟SqlSession绑定在一起的,每一个SqlSession都拥有一个新的Executor对象,由Configuration创建。
Mybatis中所有的Mapper语句的执行都是通过Executor进行的,Executor是Mybatis的一个核心接口。从其定义的接口方法我们可以看出,对应的增删改语句是通过Executor接口的update方法进行的,查询是通过query方法进行的。虽然Executor接口的实现类有BaseExecutor和CachingExecutor,而BaseExecutor的子类又有SimpleExecutor、ReuseExecutor和BatchExecutor,但BaseExecutor是一个抽象类,其只实现了一些公共的封装,而把真正的核心实现都通过方法抽象出来给子类实现,如doUpdate()、doQuery();CachingExecutor只是在Executor的基础上加入了缓存的功能,底层还是通过Executor调用的,所以真正有作用的Executor只有SimpleExecutor、ReuseExecutor和BatchExecutor。它们都是自己实现的Executor核心功能,没有借助任何其它的Executor实现,它们是实现不同也就注定了它们的功能也是不一样的。

3 XMLMapperBuilder
mapper文件的解析依赖于XMLConfigBuilder的mapperElement方法来解析mapper文件。解析过程中实质是实例化一个XMLMapperBuilder对象,然后调用其parse方法,parse方法调用的configurationElement方法是真正mapper节点解析入口,包括sql解析,缓存,等。

二、单元测试

1 生成mapper实例

运用以上相关类的功能,可以直接生成mapper的类实例。
基于Java的编程思想,设计一个基类:

BaseMapperTest:

import org.apache.ibatis.binding.MapperProxyFactory;
import org.apache.ibatis.builder.xml.XMLMapperBuilder;
import org.apache.ibatis.datasource.unpooled.UnpooledDataSource;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.session.Configuration;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.TransactionIsolationLevel;
import org.apache.ibatis.session.defaults.DefaultSqlSession;
import org.apache.ibatis.transaction.Transaction;
import org.apache.ibatis.transaction.jdbc.JdbcTransaction;
import org.springframework.core.env.PropertySource;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.ResourcePropertySource;

import java.lang.reflect.ParameterizedType;

/**
 * @author: lyx
 */
public class BaseMapperTest<T> {
    /**
     * mapper接口类(持久层接口)
     */
    private T mapper;
    /**
     * 数据库连接
     */
    private SqlSession sqlSession;
    /**
     * 执行
     */
    private static Executor executor;
    /**
     * 配置
     */
    private static Configuration configuration;

    static {
        try {
            //定义一个配置
            configuration = new Configuration();
            configuration.setCacheEnabled(false);
            configuration.setLazyLoadingEnabled(false);
            configuration.setAggressiveLazyLoading(true);
            configuration.setDefaultStatementTimeout(20);
            //读取测试环境数据库配置
            PropertySource propertySource = new ResourcePropertySource(new ClassPathResource("testdb.properties"));
            //设置数据库链接
            UnpooledDataSource dataSource = new UnpooledDataSource();
            dataSource.setDriver(propertySource.getProperty("driverClassName").toString());
            dataSource.setUrl(propertySource.getProperty("url").toString());
            dataSource.setUsername(propertySource.getProperty("username").toString());
            dataSource.setPassword(propertySource.getProperty("password").toString());
            //设置事务(测试设置事务不提交false)
            Transaction transaction = new JdbcTransaction(dataSource, TransactionIsolationLevel.READ_UNCOMMITTED, false);
            //设置执行
            executor = configuration.newExecutor(transaction);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    public BaseMapperTest(String mapperName) {
        try {
            //解析mapper文件
            Resource mapperResource = new ClassPathResource(mapperName);
            XMLMapperBuilder xmlMapperBuilder = new XMLMapperBuilder(mapperResource.getInputStream(), configuration, mapperResource.toString(), configuration.getSqlFragments());
            xmlMapperBuilder.parse();
            //直接实例化一个默认的sqlSession
            //是做单元测试,那么没必要通过SqlSessionFactoryBuilder构造SqlSessionFactory,再来获取SqlSession
            sqlSession = new DefaultSqlSession(configuration, executor, false);
            //将接口实例化成对象
            ParameterizedType pt = (ParameterizedType) this.getClass().getGenericSuperclass();
            MapperProxyFactory<T> mapperProxyFactory = new MapperProxyFactory<>((Class<T>) pt.getActualTypeArguments()[0]);
            mapper = mapperProxyFactory.newInstance(sqlSession);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    /**
     * 返回mapper实例对象
     */
    public T getMapper() {
        return mapper;
    }
}

  

配置文件:testdb.properties

driverClassName=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/demo?serverTimezone=GMT&characterEncoding=utf8&useSSL=false&allowMultiQueries=true
username=root
password=root

  

2 demo

junit或者Testng单元测试都可以实现,下面给出一个junit测试的例子

/**
 * @author lyx
 * 直接继承BaseMapperTest,并指定待持久层测试的接口即可
 */
@RunWith(SpringRunner.class)
public class BaseConfigDaoTest extends BaseMapperTest<BaseConfigDao> {

    public BaseConfigDaoTest() {
        super("mapper/BaseCodeConfigMapper.xml");
    }

    @Test
    public void selectListByCodeTest() {
        String code = "lyx";
        List<BaseConfigDTO> baseConfigList = super.getMapper().selectListByCode(code);
        Assert.assertTrue(baseConfigList.size() > 0);
    }

}

  

标签:容器,mapper,import,单元测试,apache,Executor,mybatis,org,configuration
From: https://www.cnblogs.com/luliang888/p/17527974.html

相关文章

  • Mybatis-Plus中update()和updateById()将字段更新为null
    目录简介问题描述原因概述源码分析所有策略设置为null的方案方案1:使用UpdateWrapper更新方案2:设置全局的field-strategy(不推荐)方案3:设置某个字段的field-strategy参考文章简介说明本文介绍Mybatis-Plus无法将字段更新为null的原因及解决方法。问题描述用Mybatis-......
  • 一个docker容器中只运行一个Service
    基于单一原则,一个容器里只运行一个主进程,即一个service(进程)做成一个docker镜像。多个进程在一个容器里有很多弊端,比如一个主进程更新时,其他进程也被迫重启。容器=应用+执行应用的环境而不是像虚拟机那样,把一堆进程都部署在一起。例如,service1:接收从前台来的数据,把数据存储到DB......
  • 详解Mybatis一级缓存和二级缓存
    mybatis包含了一个非常强大的查询缓存特性,他可以非常方便的定制和配置缓存。缓存可以极大的提高查询的效率mybatis系统当中默认定义了两级缓存:一级缓存和二级缓存一级缓存:默认情况之下,只有一级缓存开启(sqlSession级别的缓存)二级缓存:需要手动开启配置,需要局域namespace级别的缓......
  • 容器环境下的持续集成最佳实践:构建基于 Drone + GitFlow + K8s 的云原生语义化 CI 工
    云原生(CloudNative)是伴随的容器技术发展出现的的一个词,最早出自Pivotal公司(即开发了Spring的公司)的一本技术小册子MigratingtoCloud-NativeApplicationArchitectures,其中定义了云原生应用应当具备的一些特质,如无状态、可持续交付、微服务化等。随后云原生概念被广......
  • mystl——vector容器
    vector代码仓库:https://github.com/sjz-hub/mystl简介vector是向量,c++标准STL容器的一种特点顺序存储:容器元素严格按照线性顺序排序随机访问:支持[]和at(),时间复杂度是O(1)动态添加删除:支持在内部添加删除元素实现原理vector的成员变量iteratorbegin_指向存放的......
  • mystl之deque容器
    deque代码仓库:https://github.com/sjz-hub/mystl简介deque是双端队列,c++标准STL容器的一种特点双向访问:支持在队列的两端进行高效的插入和删除操作内部插入:支持在内部进行插入和删除操作,但是性能不如list随机访问:支持[]和at(),但是性能不如vector实现原理双端队列容......
  • mybatis的原理
    MyBatis是一个持久层框架,它的工作原理是:1.首先,MyBatis从XML映射文件中读取SQL语句,将其解析成SQL语句对象,并将SQL语句对象存储在内存中。2.然后,MyBatis将SQL语句对象与用户提供的参数绑定,生成完整的SQL语句。3.接着,MyBatis将SQL语句发送给数据库,并将查询结果映射到Jav......
  • hibernate和mybatis的区别
    Hibernate和MyBatis都是目前业界中主流的对象关系映射(ORM)框架,它们的主要区别如下。1)sql优化方面Hibernate使用HQL(HibernateQueryLanguage)语句,独立于数据库。不需要编写大量的SQL,就可以完全映射,但会多消耗性能,且开发人员不能自主的进行SQL性能优化。提供了日志、缓存......
  • 2023容器网络趋势:CNI网络插件逐渐普及,Kube-OVN受欢迎度持续攀升
    今年,Kube-OVN社区联合OSCHINA、云原生社区共同发起了《2022-2023容器网络使用情况调研》,得到了大批K8s/容器网络技术人员的关注。本调研旨在更加直观地了解各行业企业容器网络的使用现状,以及Kube-OVN在社区用户中的使用情况,以便更全面地评估容器网络发展方向,更有针对性地规划Kub......
  • 条件注解之@ConditionalOnProperty注解:通过配置文件的配置来控制配置类是否加入spring
    一、条件注解分类常见的@ConditionalOnxxx开头的注解我们称之为条件注解,常见的条件注解有class条件注解:@ConditionalOnClassbean条件注解:@ConditionalOnBean属性条件注解:@ConditionalOnProperty…@ConditionalOnProperty:如果有指定的配置,条件生效;@ConditionalOnBean:如果......