java - Spring中单元测试如何插入记录(无删除方法)
问题描述
我有使用 Spring 的 DAOjdbcTemplate
和创建读取更新(无删除)操作。
创建方法具有 ID 参数,该参数是表中的唯一键。
除了模拟 DAO,我如何才能在不违反约束的情况下实际测试创建?
使用随机 ID 有时仍然会失败
我应该覆盖 setAutoCommit 以避免添加记录吗?它仍然认为是有效的单元测试吗?
我必须事先在 SQL 中删除数据库中的记录,还是这种类型的测试有 spring 选项?
还是我应该将其视为集成测试而不是单元测试?
编辑
我正在使用 Oracle,我不能使用序列来为 ID 创建值
我们在生产中存在一些数据源(不用于测试)
解决方案
这实际上取决于这种测试的目的是什么,并不是所有的测试都是这方面的“单元测试”。
例如,如果目标是测试封装业务逻辑的“服务”,但从该服务中,有时会调用 DAO,那么最好的方法可能就是按照您的建议模拟 DAO。在这种情况下,DAO 显然不会被这个测试覆盖,但服务会。
如果目的是测试 SQL 语句(并且我假设 DAO 只包含 SQL 语句+可能将它们转换为域对象),那么模拟不是一种选择。
在这种情况下,测试应该包括对某种数据库的调用,但在这种情况下,它不再被称为单元测试(单元测试是运行非常快并且只在内存中,没有 DB,没有 I/O,等)我将其称为集成测试(正如您也建议的那样),但不同的人可能对这种测试有不同的名称。
在实践中,我们需要两种测试,因为它们测试不同的东西
那么,如何测试呢?
首先应该做出决定,应该使用哪个数据库,这里有3种方法:
- 使用真实的数据库运行,在用户之间共享,测试假定它是预先安装的
- 使用内存数据库运行
- 测试套件运行时运行DB的DB docker镜像,之后销毁
虽然关于哪种方法更好的讨论本身非常有趣,但它超出了 IMO 这个问题的范围,每个选择都有其含义。
一旦你完成了这个决定,你应该决定如何从代码中使用这个数据库。
通常弹簧测试使用以下模式:
- 测试前开启交易
- 运行测试(更改数据,甚至更改架构 - 如果需要,添加列、表)。做断言
- 无论测试结果如何,都回滚事务,使数据与测试前一样
因此,如果您对所有测试都遵循这种方法,它们将以“空”数据状态开始,这样就不会违反约束。这也有效地解决了“删除记录”问题,因为在事务处理时无论如何都会删除数据被回滚。
现在关于删除事务外的记录。
一个明显的方法是从测试中(在 DAO 之外)执行删除的 sql,以便 DAO(生产代码不会被更改)
您可以将 DataSource/JDBCTemplate 直接注入到测试中(Spring 测试完全支持这一点)并从那里调用所需的 SQL
推荐阅读
- amazon-cognito - 使用 Cognito 对 API 网关方法进行身份验证?
- middleware - 如何将旧的中间件 func 转换为新的中间件 func
- jenkins - Jenkins 声明式管道:在阶段之外运行脚本{} 块
- c - 为什么我的输出是分段失败?
- python - 时间戳减法必须具有相同的时区
- c - MPI_Bcast 有时挂起
- c - 不知道从哪里来的双倍空间
- uicollectionview - 集合单元在每个 reloadData() 调用 Swift 5 时删除项目
- node.js - 读取通过节点 lambda 函数上传到 s3 的 excel 文件
- python - 有没有办法以某种方式将 pygame gui 的屏幕转换为图像?