前言
对DB层的单测来说,如果使用mysql作为数据库,则会有两个问题,第一个问题是,目前公司的测试环境的数据库,无法通过本地直接连接,而如果使用本地mysql进行测试,则测试代码无法在另一个开发人员的机器上正确运行。第二个问题是,即使有公共的测试库,单测也是无法重复运行的,第一次的运行结果可能会影响第二次的运行,其他开发人员对测试库的操作,可能会影响你本次单测的结果。
综上,所以在这里决定使用 h2数据库(H2数据库) 的内存模式在本地进行单测。
Coding
整个项目基于 spring boot ,ORM框架使用 Mybatis.
先将 Mybatis的Mapper文件,以及数据源相关的配置写好:
数据po(省略getter,setter):
public class UserInfo {
private long id;
private String name;
private String password;
}
mapper代码:
@Mapper
public interface UserDao {
@Select("select * from user_info where id=#{id}")
UserInfo findByid(@Param("id") long id);
}
数据源配置代码:
@Configuration
public class BeanConfig {
private static final Logger LOG = LoggerFactory.getLogger(BeanConfig.class);
@Bean
public DataSource dataSource(PoolProperties poolProperties) {
LOG.info("database properties detail {}", poolProperties);
return new org.apache.tomcat.jdbc.pool.DataSource(poolProperties);
}
@Bean
@ConfigurationProperties("databaseProperties")
public PoolProperties databaseProperties() {
return new PoolProperties();
}
}
spring boot项目启动类:
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
然后在test下面的resources目录下创建配置文件 application.yml(使用yml编写):
注意:这里url中 mem 表示的是使用内存模型,不将数据库中的数据持久化到磁盘, 关于Url的参数说明
databaseProperties:
url: jdbc:h2:mem:test;MODE=MYSQL
username:
password:
driverClassName: org.h2.Driver
mybatis:
mapperLocations: com.jaky.test.demo.dao.*
UserDao对应的测试类:
@SpringBootTest
@RunWith(SpringRunner.class)
@Sql(scripts = {"classpath:sql/create_table.sql", "classpath:sql/insert_data.sql"},
config = @SqlConfig(dataSource = "dataSource"))
public class UserDaoTest {
private static final Logger LOG = LoggerFactory.getLogger(UserDaoTest.class);
@Resource
private UserDao userDao;
@Test
public void find_one_test() {
UserInfo info = userDao.findByid(1);
Assert.assertNotNull(info);
Assert.assertEquals(1, info.getId());
Assert.assertEquals("jaky.wang", info.getName());
}
}
其中在before() 方法中是对数据库进行数据初始化的逻辑,在test的resources中新建sql目录,并创建 create_table.sql,和 insert_data.sql 文件。两个文件的内容分别为:
create_table.sql:
create table user_info (
id bigint(20) auto_increment comment '主键id',
name varchar(20) not null default '' comment '名字',
password varchar(30) not null default '' comment '密码',
primary key (id)
)engine=innodb default charset=utf8;
insert_data.sql:
insert into user_info(name, password) values('jaky.wang', 'jaky.wang password');
最后执行 UserDaoTest的find_one_test() 方法即可运行,并且无论重复多少次,find_one_test()的结果都不会改变。
h2 兼容性
h2 数据库和mysql数据的一些有一些兼容性问题,例如 双引号 中的内容会被 h2 当成字段名称,其他详细的说明可查看:传送门
项目地址
本文中的代码均可在 这个仓库 的 test-demo 模块中找到。
其他
加上 @SpringBootTest 注解后,spring boot 是如何找到并初始化整个容器的?
SPringRunner在启动时,会加载在spring-boot-test包的META-INFO的spring.factories中的处理类,其中 org.springframework.boot.test.context.SpringBootTestContextCustomizerFactory 类就是处理 @SpringBootTest 注解的类。