MyBatis的JUnit測試

背景

最近項目中遇到一個場景,須要將項目中原有的DB切成MySQL。爲了驗證修改後的MyBatis的XML映射文件的SQL語法是否OK,從新部署後,在界面上一頓狂點。這種作法太Low,不只沒效率,還可能存在漏測。php

目的

經過MyBatis自帶的API,實現XML映射文件的加載,達到在本地測試的目的。無需啓動spring框架服務,靈活配置本地調試場景。html

實現方案

1. 數據庫鏈接屬性配置

配置數據庫驅動、用戶名、密碼等屬性,寫入db-config.properties文件中,如:java

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:mysql

<?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>
複製代碼

值得注意的有一下幾點:spring

  1. properties字段的resource指向在上一節定義好的數據庫鏈接屬性文件的路徑。
  2. environment節點能夠定義多個,其包含的dataSource節點中的屬性值引用來自於db-config.properties定義的變量。
  3. mapper節點能夠有幾種不一樣實現方式,詳細可查看官方文檔【傳送門】。但若是配置不當,會報XXX is not known to the MapperRegistry或者是拋出BindingException異常。最終我採用了 <mapper resource="xxx/xxx/xxx.xml"/>方式,雖然每一個XML映射文件都須要手動聲明一次,但勝在不易出錯。若是有更nice的方法,請在回覆中不吝賜教。

3. MyBatis建立Session工具類

上面兩步驟完成了一些必要的配置,接下來,就須要使用一個工具類來代替spring來實現數據庫會話建立、Mapper類加載等操做。直接上代碼:sql

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>
複製代碼

對應的接口類爲:ProjectDaobash

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方法來完成註冊。session

備註

項目中通常都會存在多個MyBatis的XML映射文件,此時須要在mybatis-config.xml文件的mappers節點中添加新的映射關係。而後能夠考慮,在測試包目錄下,新建一個相似ProjectDaoTest的測試類。在這個類中,能夠測試XML映射文件中涉及的每一個sql方法。mybatis

相關文章
相關標籤/搜索