我有使用 Spring 的 DAOjdbcTemplate
具有创建读取更新(无删除)操作。
Create 方法有 ID 参数,它是表中的唯一键。
除了模拟 DAO 之外,我如何在不违反约束的情况下实际测试创建?
使用随机 ID 有时仍然会失败
我应该覆盖 setAutoCommit 以避免添加记录吗?它仍然被认为是有效的单元测试吗?
我必须事先在 SQL 中删除数据库中的记录吗?或者是否有针对此类测试的 spring 选项?
或者我应该将其视为集成测试而不是单元测试?
EDIT
我正在使用 Oracle,无法使用序列为 ID 创建值
我们在生产中存在一些数据源(不用于测试)
这实际上取决于此类测试的目的是什么,并非所有测试都是这方面的“单元测试”。
例如,如果目标是测试封装业务逻辑的“服务”,但从该服务中,有时会调用 DAO,那么最好的方法可能就是按照您的建议模拟 DAO。
在这种情况下,DAO 显然不会被该测试覆盖,但服务会被覆盖。
如果目的是测试 SQL 语句(并且我假设 DAO 只包含 SQL 语句+可能将它们转换为域对象),那么模拟不是一个选择。
在这种情况下,测试应该包括对某种数据库的调用,但在这种情况下,它不再被称为单元测试(单元测试是运行非常快并且仅在内存中运行的东西,没有数据库,没有 I/O,等)我将其称为集成测试(正如您也建议的那样),但是不同的人对此类测试可能有不同的名称。
在实践中,我们需要两种测试,因为它们测试不同的东西
那么,如何测试呢?
首先应该决定使用哪个数据库,这里有3种方法:
- 使用真实数据库运行,在用户之间共享,测试假设其已预先安装
- 使用内存数据库运行
- 测试套件运行时运行数据库的DB docker镜像,然后销毁它
虽然关于哪种方法更好的讨论本身就非常有趣,但在我看来,这超出了这个问题的范围,但每种选择都有其含义。
完成此决定后,您应该决定如何从代码中使用此数据库。
通常弹簧测试使用以下模式:
- 测试前打开交易
- 运行测试(更改数据,甚至更改架构 - 如果需要,添加列、表)。做断言
- 无论测试结果如何,回滚事务,使数据与测试前一样
因此,如果您对所有测试都遵循这种方法,它们将从“空”数据状态开始,这样就不会违反约束条件
这也有效地解决了“删除记录”的问题,因为当事务回滚时数据无论如何都会被删除。
现在关于事务外记录的删除。
一个明显的方法是直接从测试中(在DAO之外)执行删除的sql,这样DAO(生产代码不会被更改)
您可以将 DataSource/JDBCTemplate 直接注入到测试中(Spring 测试完美支持这一点)并从那里调用所需的 SQL
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)