SoFunction
Updated on 2025-03-09

Mybatis unit testing process (no need to start the container)

1. Brief analysis of related categories

1 Configuration

MyBatis will read all configuration files at startup and then load them into memory. The Configuration class is the class that hosts the entire configuration.

SqlSessionFactoryBuilder calls the build method to create SqlSessionFactory, and SqlSessionFactory requires the Configuration Configuration Center to provide the creation conditions. In the build method, XMLConfigBuilder initializes the XML file stream and parse returns the Configuration. Before returning, you need to use parseConfiguration to truly set the information for the Configuration. XPathParser is responsible for converting the information under the node into XNode objects for easy access.

2 Executor

Executor is bound to SqlSession. Each SqlSession has a new Executor object created by Configuration.

All Mapper statements in Mybatis are executed through Executor, which is a core interface of Mybatis.

From the interface method it defines, we can see that the corresponding add-and-deletion statements are performed through the update method of the Executor interface, and the query is performed through the query method.

Although the implementation classes of the Executor interface include BaseExecutor and CachingExecutor, and the subclasses of BaseExecutor include SimpleExecutor, ReuseExecutor and BatchExecutor, BaseExecutor is an abstract class that only implements some public encapsulation, and abstracts the real core implementations into subclass implementations through methods, such as doUpdate() and doQuery(); CachingExecutor only adds the cache function to the Executor, and the underlying layer is still called through Executor, so the real function of Executor is SimpleExecutor, ReuseExecutor and BatchExecutor.

They are all core Executor functions implemented by themselves. Without any other Executor implementation, their different implementations are destined to be different.

3 XMLMapperBuilder

The parsing of mapper files depends on the mapperElement method of XMLConfigBuilder to parse mapper files.

The essence of the parse process is to instantiate an XMLMapperBuilder object and then call its parse method. The configurationElement method called by the parse method is the real mapper node parsing entrance, including SQL parsing, cache, etc.

2. Unit test

1 Generate a mapper instance

Using the functions of the above related classes, you can directly generate a class instance of the mapper.

Based on Java programming ideas, design a base class:

BaseMapperTest:

import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;

import ;

/**
 * @author: lyx
 */
public class BaseMapperTest<T> {
    /**
      * mapper interface class (persistence layer interface)
      */
    private T mapper;
    /**
      * Database connection
      */
    private SqlSession sqlSession;
    /**
      * implement
      */
    private static Executor executor;
    /**
      * Configuration
      */
    private static Configuration configuration;

    static {
        try {
            //Define a configuration            configuration = new Configuration();
            (false);
            (false);
            (true);
            (20);
            //Read the test environment database configuration            PropertySource propertySource = new ResourcePropertySource(new ClassPathResource(""));
            //Set the database link            UnpooledDataSource dataSource = new UnpooledDataSource();
            (("driverClassName").toString());
            (("url").toString());
            (("username").toString());
            (("password").toString());
            //Set transactions (test set transactions do not commit false)            Transaction transaction = new JdbcTransaction(dataSource, TransactionIsolationLevel.READ_UNCOMMITTED, false);
            //Set execution            executor = (transaction);
        } catch (Exception e) {
            ();
        }
    }
    public BaseMapperTest(String mapperName) {
        try {
            //Parse mapper file            Resource mapperResource = new ClassPathResource(mapperName);
            XMLMapperBuilder xmlMapperBuilder = new XMLMapperBuilder((), configuration, (), ());
            ();
            //Directly instantiate a default sqlSession            //It is for unit testing, so there is no need to construct SqlSessionFactory through SqlSessionFactoryBuilder, and then get SqlSession            sqlSession = new DefaultSqlSession(configuration, executor, false);
            //Instantiate the interface into an object            ParameterizedType pt = (ParameterizedType) ().getGenericSuperclass();
            MapperProxyFactory<T> mapperProxyFactory = new MapperProxyFactory<>((Class<T>) ()[0]);
            mapper = (sqlSession);
        } catch (Exception e) {
            ();
        }
    }
    /**
      * Return mapper instance object
      */
    public T getMapper() {
        return mapper;
    }
}

Configuration file:

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

2 demo

Both junit or Testng unit tests can be implemented. Here is an example of junit tests

/**
  * @author lyx
  * Directly inherit BaseMapperTest and specify the interface to be tested on persistent layer
  */
@RunWith()
public class BaseConfigDaoTest extends BaseMapperTest<BaseConfigDao> {

    public BaseConfigDaoTest() {
        super("mapper/");
    }

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

}

Summary

The above is personal experience. I hope you can give you a reference and I hope you can support me more.