java - 测试是否发出了良好的查询

标签 java unit-testing mocking

我经常发现自己针对数据库调用编写单元测试,而且我总是遇到同样的问题:如何验证是否向数据库发送了正确的查询?

例如,我有一个类将以下列形式向数据库发送最终更新:

update credential set password_hash = ?, password_crypt = ?, password_plain = ? where id = ?

(这是一个密码迁移工具,请不要介意password_plain字段的安全问题)

为此类编写测试类,我模拟了数据库访问类(在本例中我使用的是 Spring JDBCTemplate)并捕获了发出的 sql。获得 sql 后,我将执行以下检查:

String space = "\\s+";
String optSpace = "\\s*";
String something = ".+";
String optSomething = ".*";

sql = sql.toLowerCase();
assertTrue(sql.matches(optSpace + "update" + space + "credential" + space + "set" + space + something));
assertTrue(sql.matches(something + space + "set" + space + optSomething + "password_hash" + optSpace + "=" + optSpace + "\\?" + something + "where" + something));
assertTrue(sql.matches(something + space + "set" + space + optSomething + "password_crypt" + optSpace + "=" + optSpace + "\\?" + something + "where" + something));
assertTrue(sql.matches(something + space + "set" + space + optSomething + "password_plain" + optSpace + "=" + optSpace + "\\?" + something + "where" + something));
assertTrue(sql.matches(something + space + "where" + space + optSomething + "id" + optSpace + "=" + optSpace + "\\?" + optSomething));

通过这些检查,我确实在验证发出的 SQL 是否包含更新中最重要的部分,例如:

  • 正在更新正确的表格
  • 所有 3 个字段都更新为作为参数传递的值
  • id 被用在 where 语句中,其值作为参数

我可以简单地验证发出的查询是否正是上面预期的查询,但这会使测试对 future 的更改过于严格,并且如果查询的任何部分发生更改,即使更新保持正确,也会强制失败。因为我认为编写测试主要是为了将来使用(当您更改软件并为此需要更多保证时)而不是现在,所以此选项会使测试有点无用。

好吧,最后,我声明我的问题:我们有哪些更好的选择来验证发布的 SQL?

我看到很多项目创建了带有少量数据的小型嵌入式数据库,用于测试处理数据库的类,但我想编写一个更纯粹的单元测试替代方案(如果我可以这样称呼)

最佳答案

我认为除了针对真实数据库(即使它是嵌入式等)进行测试之外,没有其他好的选择。目前您正在测试您的 SQL 在语法上是否有效,但它是否真的有效。例如你知道它是否会违反约束等......

模拟等一切都很好,但在某些阶段你必须针对数据库进行测试。我会确保在可能的情况下您不会针对数据库进行测试,然后硬着头皮围绕一个小型数据库构建测试(具有适当的回滚/重建等)以实际确认正确的数据库功能。

关于java - 测试是否发出了良好的查询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14947537/

相关文章:

java - 如何在插入排序中保持数据配对

javascript - 如何更改 Jest 中模拟模块中函数的模拟实现

c++ - 哪些测试框架不会替换 "new"和 "malloc"?

reactjs - 如何在用 jest 进行单元测试时替换全局函数

javascript - 在 AngularJS 中模拟 Controller 单元测试的依赖服务

java - 我应该对哪些方法进行 JUnit 测试 - 如何模拟具有许多依赖项的方法

c# - 在 Moq Callback() 调用中设置变量值

java - JPA持久性问题

java - Java中Integer转换为int作为栈的返回类型

java - Java 中的 PriorityQueue 说明