MyBatis的JUnit测试

发表于:2019-6-10 10:40

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:七印miss    来源:掘金

  背景
  最近项目中遇到一个场景,需要将项目中原有的DB切成MySQL。为了验证修改后的MyBatis的XML映射文件的SQL语法是否OK,重新部署后,在界面上一顿狂点。这种做法太Low,不仅没效率,还可能存在漏测。
  目的
  通过MyBatis自带的API,实现XML映射文件的加载,达到在本地测试的目的。无需启动spring框架服务,灵活配置本地调试场景。
  实现方案
  1. 数据库连接属性配置
  配置数据库驱动、用户名、密码等属性,写入db-config.properties文件中,如:
   mysql.driver=com.mysql.cj.jdbc.Driver
  mysql.url=jdbc:mysql://localhost:3306/qiyin?useUnicode=true&characterEncoding=utf8
  mysql.username=root
  mysql.password=123456
  2. MyBatis配置文件
  MyBatis配置文件的各个字段,在官网有详细介绍。
  如下是我的配置文件mybatis-config.xml:
   <?xml version="1.0" encoding="UTF-8"?>
  <!DOCTYPE configuration
  PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
  "http://mybatis.org/dtd/mybatis-3-config.dtd">
  <!--实现mybatis与数据库的连接  -->
  <configuration>
  <!-- 引入属性配置文件 -->
  <properties resource="db-config.properties"/>
  <!-- 指定日志的具体实现 -->
  <settings>
  <setting name="logImpl" value="STDOUT_LOGGING"/>
  <!--<setting name="logImpl" value="LOG4J2"/>-->
  </settings>
  <typeAliases>
  <package name="me.ifight.bean"/>
  </typeAliases>
  <environments default="development">
  <environment id="development">
  <!-- 采用JDBC管理事务-->
  <transactionManager type="JDBC"/>
  <dataSource type="POOLED">
  <property name="driver" value="${mysql.driver}"/>
  <property name="url" value="${mysql.url}"/>
  <property name="username" value="${mysql.username}"/>
  <property name="password" value="${mysql.password}"/>
  </dataSource>
  </environment>
  </environments>
  <!-- 注册mapper -->
  <mappers>
  <mapper resource="mybatisMapper/ProjectMapper.xml"/>
  </mappers>
  </configuration>
  值得注意的有一下几点:
  properties字段的resource指向在上一节定义好的数据库连接属性文件的路径。
  environment节点可以定义多个,其包含的dataSource节点中的属性值引用来自于db-config.properties定义的变量。
  mapper节点可以有几种不同实现方式,详细可查看官方文档【传送门】。但如果配置不当,会报XXX is not known to the MapperRegistry或者是抛出BindingException异常。最终我采用了
  <mapper resource="xxx/xxx/xxx.xml"/>方式,虽然每个XML映射文件都需要手动声明一次,但胜在不易出错。如果有更nice的方法,请在回复中不吝赐教。
  3. MyBatis创建Session工具类
  上面两步骤完成了一些必要的配置,接下来,就需要使用一个工具类来代替spring来实现数据库会话创建、Mapper类加载等操作。直接上代码:
   public class MybatisUtil {
  private static final LogUtil log = LogUtil.getLogger(MybatisUtil.class, MybatisUtil.class.getSimpleName());
  /**
  * MyBatis配置文件路径
  */
  private static final String MYBATIS_CONFIG_PATH = "mybatis-config.xml";
  private static SqlSessionFactory factory;
  private static ThreadLocal<SqlSession> localSessions = new ThreadLocal<>();
  /**
  * 加载并解析配置文件
  */
  static {
  try(
  InputStream in = Resources.getResourceAsStream(MYBATIS_CONFIG_PATH)
  ) {
  SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
  factory = builder.build(in);
  } catch (IOException e) {
  log.error("SqlSessionFactory init error", e);
  }
  }
  /**
  * 常见会话
  * @return
  */
  public static SqlSession getSession(){
  SqlSession sqlSession = localSessions.get();
  if (sqlSession == null){
  sqlSession = factory.openSession();
  localSessions.set(sqlSession);
  }
  if (sqlSession == null){
  log.error("#getSession error, session is nulll");
  } else {
  log.info("#getSession successfully");
  }
  return sqlSession;
  }
  /**
  * 销毁会话
  */
  public static void closeSession(){
  SqlSession sqlSession = localSessions.get();
  if (sqlSession != null){
  sqlSession.close();
  localSessions.remove();
  }
  log.info("#closeSession successfully");
  }
  }
  4. 测试验证材料
  在项目的resources目录中,已经有一个MyBatis的XML映射文件:mybatisMapper/ProjectMapper.xml。模拟一个select方法selectProjectsByUserName
  <select id="selectProjectsByUserName" resultMap="AllColumnMap">
   SELECT <include refid="all_column"/>
  FROM todo_project
  where created_user_name = #{userName}
  order by last_time desc
  LIMIT 1000
  </select>
   对应的接口类为:ProjectDao
  public interface ProjectDao {
  List<ProjectDO> selectProjectsByUserName(@Param("userName") String userName);
  }
 5. JUnit测试脚本
   public class ProjectDaoTest{
  private static final LogUtil log = LogUtil.getLogger(ProjectDaoTest.class, ProjectDaoTest.class.getSimpleName());
  private SqlSession sqlSession;
  private ProjectDao projectDao;
  @Before
  public void setUp() throws Exception{
  log.info("#setUp start...");
  sqlSession = MybatisUtil.getSession();
  projectDao = sqlSession.getMapper(ProjectDao.class);
  }
  @Test
  public void testSelectProjectsByUserName(){
  List<ProjectDO> projects = projectDao.selectProjectsByUserName("admin");
  Assert.assertTrue(CollectionUtils.isNotEmpty(projects));
  }
  @After
  public void tearDown() throws Exception{
  log.info("#tearDown start...");
  sqlSession.commit();
  MybatisUtil.closeSession();
  }
  }
  测试脚本的关键在于,使用SqlSession实例的getMapper()方法加载已经注册的Mapper对象。
  所谓的已经注册是指在解析MyBatis配置文件时,通过加载MyBatis配置文件中的mappers节点的信息,调用MapperRegistry实例的addMappers方法来完成注册。
  备注
  项目中一般都会存在多个MyBatis的XML映射文件,此时需要在mybatis-config.xml文件的mappers节点中添加新的映射关系。然后可以考虑,在测试包目录下,新建一个类似ProjectDaoTest的测试类。在这个类中,可以测试XML映射文件中涉及的每个sql方法。
 
     上文内容不用于商业目的,如涉及知识产权问题,请权利人联系博为峰小编(021-64471599-8017),我们将立即处理。
《2023软件测试行业现状调查报告》独家发布~

关注51Testing

联系我们

快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计 发展历程

法律顾问:上海兰迪律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2024
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪ICP备05003035号

沪公网安备 31010102002173号