Introduction
Translations
Users can read about MyBatis-Spring-Boot-Starter-Test in the following translations:
What is MyBatis-Spring-Boot-Starter-Test?
The MyBatis-Spring-Boot-Starter-Test help creating a test cases for MyBatis component using the MyBatis-Spring-Boot-Starter.
By using this module you will can be:
- Can use the
@MybatisTest
that setup test components for testing pure MyBatis component - Can import dependency artifacts for performing tests for pure MyBatis component
Requirements
The MyBatis-Spring-Boot-Starter-Test requires following versions:
MyBatis-Spring-Boot-Starter-Test | Spring Boot | Java |
---|---|---|
3.0 | 3.0 - 3.4 | 17 or higher |
2.3 | 2.7 | 8 or higher |
Installation
Maven
If you are using Maven just add the following dependency to your pom.xml
:
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter-test</artifactId>
<version>3.0.4</version>
<scope>test</scope>
</dependency>
Gradle
If using gradle add this to your build.gradle
:
dependencies {
testImplementation("org.mybatis.spring.boot:mybatis-spring-boot-starter-test:3.0.4")
}
Using @MybatisTest
The @MybatisTest
can be used if you want to test MyBatis components(Mapper interface and SqlSession
).
By default it will configure MyBatis(MyBatis-Spring) components(SqlSessionFactory
and SqlSessionTemplate
),
configure MyBatis mapper interfaces and configure an in-memory embedded database.
MyBatis tests are transactional and rollback at the end of each test by default,
for more details refer to the relevant section in the Spring Reference Documentation.
Also regular @Component
beans will not be loaded into the ApplicationContext
.
Test for Mapper interface
if you create a test case for following mapper interface, you add just @MybatisTest
on your test case class.
Mapper interface :
package sample.mybatis.mapper;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import sample.mybatis.domain.City;
@Mapper
public interface CityMapper {
@Select("SELECT * FROM CITY WHERE state = #{state}")
City findByState(@Param("state") String state);
}
TestCase class :
package sample.mybatis.mapper;
import org.junit.jupiter.api.Test;
import org.junit.runner.RunWith;
import org.mybatis.spring.boot.test.autoconfigure.MybatisTest;
import sample.mybatis.domain.City;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.junit4.SpringRunner;
import static org.assertj.core.api.Assertions.assertThat;
@RunWith(SpringRunner.class)
@MybatisTest
public class CityMapperTest {
@Autowired
private CityMapper cityMapper;
@Test
public void findByStateTest() {
City city = cityMapper.findByState("CA");
assertThat(city.getName()).isEqualTo("San Francisco");
assertThat(city.getState()).isEqualTo("CA");
assertThat(city.getCountry()).isEqualTo("US");
}
}
Test for DAO pattern
if you create a test case for following DAO class, you add just @MybatisTest
and @Import
on your test case class.
DAO class :
package sample.mybatis.dao;
import org.apache.ibatis.session.SqlSession;
import sample.mybatis.domain.City;
import org.springframework.stereotype.Component;
@Component
public class CityDao {
private final SqlSession sqlSession;
public CityDao(SqlSession sqlSession) {
this.sqlSession = sqlSession;
}
public City selectCityById(long id) {
return this.sqlSession.selectOne("selectCityById", id);
}
}
TestCase class :
package sample.mybatis.dao;
import org.junit.jupiter.api.Test;
import org.junit.runner.RunWith;
import org.mybatis.spring.boot.test.autoconfigure.MybatisTest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Import;
import org.springframework.test.context.junit4.SpringRunner;
import sample.mybatis.domain.City;
import static org.assertj.core.api.Assertions.assertThat;
@RunWith(SpringRunner.class)
@MybatisTest
@Import(CityDao.class)
public class CityDaoTest {
@Autowired
private CityDao cityDao;
@Test
public void selectCityByIdTest() {
City city = cityDao.selectCityById(1);
assertThat(city.getName()).isEqualTo("San Francisco");
assertThat(city.getState()).isEqualTo("CA");
assertThat(city.getCountry()).isEqualTo("US");
}
}
Using a real database
The In-memory embedded databases generally work well for tests since they are fast and don’t require any developer installation.
However if you prefer to run tests against a real database, you can use the @AutoConfigureTestDatabase
as follow:
package sample.mybatis.mapper;
// ...
import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase;
@RunWith(SpringRunner.class)
@MybatisTest
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
public class CityMapperTest {
// ...
}
Prevent detecting a real @SpringBootApplication
The @MybatisTest
will detect a class that annotated @SpringBootApplication
by default.
Therefore by depend on bean definition methods, there is case that an unexpected error is occurred or unnecessary components are loaded into ApplicationContext
.
This behavior can prevent by creating a @SpringBootApplication
class into same package as test class as follow:
package sample.mybatis.mapper;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
class MapperTestApplication {
}
Use together with other @***Test
If you use the @MybatisTest
together with other @***Test
(e.g. @WebMvcTest
),
Please consider to use the @AutoConfigureMybatis
because @***Test
annotation cannot specify two or more on same test.
Target classes for testing:
@RestController
public class PingController {
PingMapper mapper;
PingController(PingMapper mapper) {
this.mapper = mapper;
}
@GetMapping("ping")
String ping() {
return mapper.ping();
}
}
@Mapper
public interface PingMapper {
@Select("SELECT 'OK'")
String ping();
}
Test class:
@RunWith(SpringRunner.class)
@WebMvcTest
@AutoConfigureMybatis // Specify instead of @MybatisTest
public class PingTests {
@Autowired
private MockMvc mvc;
@Test
public void ping() throws Exception {
this.mvc.perform(get("/ping"))
.andExpect(status().isOk())
.andExpect(content().string("OK"));
}
}
Using @MybatisTest on JUnit 5
The @MybatisTest
can be used on JUnit 5.
@ExtendWith(SpringExtension.class)
@MybatisTest
public class CityMapperTest {
// ...
}
Since 2.0.1, the @ExtendWith(SpringExtension.class)
can omit as follow:
@MybatisTest
public class CityMapperTest {
// ...
}
Appendix
Imported auto-configuration
The @MybatisTest
will import following auto-configuration classes.
org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration
org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration
org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration
org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration
org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration
org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration
org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration
org.springframework.boot.autoconfigure.sql.init.SqlInitializationAutoConfiguration
org.mybatis.spring.boot.autoconfigure.MybatisLanguageDriverAutoConfiguration
org.mybatis.spring.boot.autoconfigure.MybatisAutoConfiguration
Running Samples
The project provides two samples so you play and experiment with them.
Category | Sample | Description |
---|---|---|
Core | 1st Sample | Show the simplest scenario with just a mapper and a bean where the mapper is injected into. This is the sample we saw in the Quick Setup section. |
2nd Sample | Shows how to use a Mapper that has its statements in an xml file and Dao that uses an SqlSessionTemplate . | |
JVM Language | 3rd Sample | Shows how to use with kotlin. |
4th Sample | Shows how to use with groovy. |