MyBatis JUnit test

background

Recent project encountered a scenario, the project will need to cut any original DB MySQL. In order to verify the modified MyBatis XML mapping files of SQL syntax is OK, after redeployment, meal mad at the interface point. This approach is too Low, not only inefficient, but also may exist leakage test.

purpose

By MyBatis own API, to achieve loaded XML mapping files, to achieve the purpose of testing locally. Spring frame without launching the service, flexible configuration local debugging scenarios.

Implementation

1. Database Connection properties

Configuration database driver, user name, password, so write db-config.properties file, such as:

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 configuration file

MyBatis configuration file of each field, are described in detail in the official website [Portal] .
Here is my profile 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>
复制代码

It is noteworthy that there are the following points:

  1. resource properties field directed in a path defined database connection properties file.
  2. environment can define multiple nodes, the node comprising dataSource attribute value in the reference variable from db-config.properties defined.
  3. mapper nodes can have several different implementations, you can view detailed official document [Portal] . However, when configured improperly, newspaper XXX is not known to the MapperRegistryor throw an BindingExceptionexception. I ended up using <mapper resource="xxx/xxx/xxx.xml"/>way, although each XML mapping file will need to manually declare once, but wins in less error-prone. If there are more nice way, please let us know in the reply.

3. MyBatis create Session Tools

The above two steps necessary to complete the configuration, then, it is necessary to use a tool to achieve spring class instead create a database session, loading and other operations Mapper classes. Directly on the code:

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. Verify test material

In the resources directory of the project, there have been a MyBatis XML mapping file is: mybatisMapper / ProjectMapper.xml. Select a simulation method 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>
复制代码

A corresponding interface class: ProjectDao

public interface ProjectDao {
    List<ProjectDO> selectProjectsByUserName(@Param("userName") String userName);
}
复制代码

5. JUnit test scripts

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();
    }
}
复制代码

The key test scripts that use SqlSession instance getMapper () method to load Mapper object has been registered. It refers to the so-called already registered MyBatis configuration file when parsing through information MyBatis mappers node configuration file is loaded, call addMappers method MapperRegistry instance to complete the registration.

Remark

Usually there are multiple MyBatis XML mapping file in your project, then you need to add a new node mapping in the mappers mybatis-config.xml file. It may then be considered, in the test package directory, similar to a new class ProjectDaoTest the test. In this class, you can test each method sql XML mapping files involved.

Guess you like

Origin juejin.im/post/5cfa0bf451882568862d6911