春季如何在单元测试中插入记录(无删除方法)

时间:2018-07-11 05:10:46

标签: java spring unit-testing dao jdbctemplate

我使用Spring的jdbcTemplate进行创建读取更新(不删除)操作的DAO。

创建方法的ID参数是表中的唯一键。

除了模拟DAO,我如何才能在不违反约束的情况下实际测试创建?

使用随机ID有时仍会失败

我应该重写setAutoCommit以避免添加记录吗?仍然认为有效的单元测试吗?

我必须预先在SQL中删除数据库中的记录,还是这种类型的测试有spring选项?

还是应该将其视为集成测试而不是单元测试?

编辑

我正在使用Oracle,我无法使用序列来为ID创建值

我们在生产中存在一些数据源(不用于测试)

1 个答案:

答案 0 :(得分:0)

这实际上取决于这种测试的目的是什么,并不是所有测试在这方面都是“单元测试”。

例如,如果目标是测试封装业务逻辑的“服务”,但是有时从此服务中调用DAO,那么最好的方法可能就是按照您的建议模拟DAO。 在这种情况下,该测试显然不会涵盖DAO,但该服务将涵盖。

如果目的是测试SQL语句(并且我假设DAO除了SQL语句外不包含任何内容,也许将它们转换为域对象),那么就不能选择模拟。

在这种情况下,测试应该包括对某种数据库的调用,但是在这种情况下,它不再称为单元测试(单元测试运行起来非常快,并且仅在内存中运行,没有DB,没有I / O等),我将其称为集成测试(也如您所建议),但是对于这种测试,不同的人可能会有不同的名字。

实际上,我们需要两种测试,因为它们测试的是不同的东西

那么,如何测试呢?

首先应该做出决定,应该使用哪个数据库,这里有3种方法:

  1. 使用真实数据库运行,用户之间共享,测试假定其已预先安装
  2. 使用内存数据库运行
  3. 在测试套件运行时运行数据库的DB docker映像,然后销毁它

虽然哪种方法更好的讨论本身很有趣,但在IMO的问题范围之外,每个选择都有其含义。

完成此决定后,您应该从代码中决定如何使用此数据库。

通常,弹簧测试使用以下模式:

  1. 在测试前打开交易
  2. 运行测试(更改数据,甚至更改架构-如果需要,添加列,表)。做断言
  3. 无论测试结果如何,都应回滚事务,以便数据将像测试前一样

因此,如果您对所有测试都遵循这种方法,那么它们将从“空”数据状态开始,这样就不会出现违反约束的情况 这也有效地解决了“删除记录”问题,因为在回滚事务时,无论如何都会删除数据。

现在有关在交易之外删除记录。

一种明显的方法是直接从测试(在DAO外部)执行删除的sql,以便DAO(不会更改生产代码)

您可以直接将DataSource / JDBCTemplate注入测试中(Spring测试完全支持此操作),然后从那里调用所需的SQL