Spring 单元测试中使用@Sql准备数据

本文介绍如何利用Spring框架中的@Sql注解简化单元测试中的数据准备工作。通过执行SQL脚本来设置测试环境,并探讨了@Sql注解的各种属性及配置选项,如@SqlConfig和@SqlMergeMode,帮助开发者更高效地管理和回滚测试数据。

在写单元测试时,往往需要在数据库中准备对应的测试数据。
我们可以在测试用例中,通过代码的方式往数据库中插入数据。但这么做会使测试代码比较臃肿。
个人觉得,通过sql脚本去导入数据,再结合@Transactional注解对数据进行回滚,是一种更好的方案。
为此,spring为我们准备了很有用的注解@Sql。

@Sql

@Sql注解可以执行SQL脚本,也可以执行SQL语句。它既可以加上类上面,也可以加在方法上面。
默认情况下,方法上的@Sql注解会覆盖类上的@Sql注解,但可以通过@SqlMergeMode注解来修改此默认行为。
@Sql有下面的属性:

  • config:与注解@SqlConfig作用一样,用来配置“注释前缀”,“分隔符”等。
  • executionPhase:决定SQL脚本或语句什么时候会执行,默认是BEFORE_TEST_METHOD。
  • statements:配置要一起执行的SQL语句。
  • scripts:配置SQL脚本路径。
  • value:scripts的别名,它不能和scripts同时配置,但statements可以。

例如:

@Sql({ "/drop_schema.sql", "/create_schema.sql" })
@Sql(scripts = "/insert_data1.sql", statements = "insert into student(id, name) values (100, 'Shiva')")
@ExtendWith(SpringExtension.class)
@ContextConfiguration(classes = AppConfig.class)
public class SqlTest {
	@Autowired
	private JdbcTemplate jdbcTemplate;

	@Test
	public void fetchRows1() {
		List<Map<String, Object>> students = jdbcTemplate.queryForList("SELECT * FROM student");
		assertEquals(3, students.size());
	}

	@Sql("/insert_more_data1.sql")
	@Test
	public void fetchRows2() {
		List<Map<String, Object>> students = jdbcTemplate.queryForList("SELECT * FROM student");
		assertEquals(5, students.size());
	}
} 

drop_schema.sql :

drop table if exists student; 

create_schema.sql :

CREATE TABLE student (
  id INT NOT NULL,
  name VARCHAR(50) NOT NULL,
  PRIMARY KEY(id)
); 

insert_data1.sql :

insert into student(id, name) values (101, 'Mohan');
insert into student(id, name) values (102, 'Krishna'); 

insert_more_data1.sql :

insert into student(id, name) values (103, 'Indra');
insert into student(id, name) values (104, 'Chandra'); 

@SqlConfig

@SqlConfig用于配置如何去解释@Sql注解中指定的Sql脚本。
@SqlConfig可以用于类上,也可以用于方法上。
@Sql注解也有一个config属性,作用与@SqlConfig相同,不同的是作用域只在对应的@Sql注解范围。它的优先级也大于类注解的@SqlConfig。

  • blockCommentStartDelimiter:多行注释开始字符,默认是/*。
  • blockCommentEndDelimiter:多行注释结束字符,默认是*/。
  • commentPrefix:单行注释前缀,默认是–。
  • commentPrefixes:指定多个单行注释前缀,默认是["–"]。
  • dataSource:指定脚本执行的数据库的名字,只有在多个数据源时需要指定。
  • encoding:指定sql脚本文件的字符编码。
  • errorMode:配置错误模式,默认是SqlConfig.ErrorModeDEFAULT
  • separator:配置脚本语句分隔符,默认是’\n’。
  • transactionManager:指定transactionManager bean,只有有多个transactionManager时需要指定。
  • transactionMode:指定脚本执行的事务模式,默认是SqlConfig.TransactionModeDEFAULT

例子:

@SqlConfig(commentPrefix = "#")
@Sql({ "/drop_schema.sql", "/create_schema.sql" })
@Sql(scripts = { "/insert_data2.sql" })
@ExtendWith(SpringExtension.class)
@ContextConfiguration(classes = AppConfig.class)
public class SqlConfigTest {
	@Autowired
	private JdbcTemplate jdbcTemplate;

	@Test
	public void fetchRows1() {
		List<Map<String, Object>> students = jdbcTemplate.queryForList("SELECT * FROM student");
		assertEquals(2, students.size());
	}

	@Sql(scripts = "/insert_more_data2.sql", config= @SqlConfig(commentPrefix = "~"))
	@Test
	public void fetchRows2() {
		List<Map<String, Object>> students = jdbcTemplate.queryForList("SELECT * FROM student");
		assertEquals(4, students.size());
	}
} 

insert_data2.sql :

#Insert initial data

insert into student(id, name) values (101, 'Mohan');
insert into student(id, name) values (102, 'Krishna'); 

@SqlMergeMode

@SqlMergeMode可以加在类上,也可以加在方法上。用于指示方法上的@Sql和类上@Sql注解配置是否合并。方法上的@SqlMergeMode注解优先级更高。默认值是SqlMergeMode.MergeModeOVERRIDE

例:

@SqlMergeMode(MergeMode.MERGE)
@Sql({ "/drop_schema.sql", "/create_schema.sql", "/insert_data1.sql" })
@ExtendWith(SpringExtension.class)
@ContextConfiguration(classes = AppConfig.class)
public class SqlMergeModeTest {
	@Autowired
	private JdbcTemplate jdbcTemplate;

	@Sql(statements = "insert into student(id, name) values (100, 'Shiva')")	
	@Test
	public void fetchRows1() {
		List<Map<String, Object>> students = jdbcTemplate.queryForList("SELECT * FROM student");
		assertEquals(3, students.size());
	}

	@SqlMergeMode(MergeMode.OVERRIDE)	
	@Sql("/insert_more_data1.sql")
	@Test
	public void fetchRows2() {
		List<Map<String, Object>> students = jdbcTemplate.queryForList("SELECT * FROM student");
		assertEquals(5, students.size());
	}
} 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

xiegwei

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值