Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/345.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/unit-testing/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 测试是否发出了正确的查询_Java_Unit Testing_Mocking - Fatal编程技术网

Java 测试是否发出了正确的查询

Java 测试是否发出了正确的查询,java,unit-testing,mocking,Java,Unit Testing,Mocking,我经常发现自己在编写针对数据库调用的单元测试,我总是遇到同样的问题:如何验证是否向数据库发送了一个好的查询 例如,我有一个类,它将以以下形式向数据库发送最终更新: update credential set password_hash = ?, password_crypt = ?, password_plain = ? where id = ? (这是一个密码迁移工具,请不要介意password\u plain字段的安全问题) 在为这个类编写测试类时,我模拟了数据库访问类(在本例中,我使用的

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

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

update credential set password_hash = ?, password_crypt = ?, password_plain = ? where id = ?
(这是一个密码迁移工具,请不要介意
password\u plain
字段的安全问题)

在为这个类编写测试类时,我模拟了数据库访问类(在本例中,我使用的是SpringJDBCTemplate)并捕获了发布的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
    语句中使用,其值作为参数
我可以简单地验证发出的查询是否正是上面所期望的查询,但这会使测试对将来的更改限制过大,并且如果查询的任何部分被更改,即使更新保持正确,也会导致失败。因为我认为编写测试主要是为了将来使用(当您正在更改软件并且需要更多的保证时),而不是现在,所以这个选项会使测试变得毫无用处

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


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

我认为没有一个好的替代方案来测试真实的数据库(即使它是嵌入式的等等)。目前,您正在测试您的SQL在语法上是否有效,但它是否真的有效。e、 你知道它是否会违反约束条件等吗


模拟等都是很好的,但在某个阶段,您必须对数据库进行测试。我会确保在可能的情况下,您不会对数据库进行测试,然后咬紧牙关,围绕一个小型数据库构建测试(使用适当的回滚/重建等),以实际确认正确的数据库功能

我恳请您重新考虑这些测试的好处,因为

  • 它正在验证实现而不是行为
  • 当您将来更改SQL查询时(或者某人只是错误地添加了一个无害的空间),即使您保留了行为,测试也会失败
对于最后一个DataAccessLayer,我建议编写一个集成测试。一个运行在真实但最小的数据库上的数据库。当然,这些测试将是缓慢的,但他们提供的信心是值得的


因此,针对GetCustomers()编写测试,并验证返回的DTO是否包含正确的数据,而不是验证您发出的SQL查询是否为X。

不要断言您的SQL。这是毫无意义的。最后,您将把传递的sql字符串与另一个字符串(也是由您创建的,因此没有验证)进行比较,或者您必须实现自己的数据库。相反,只需使用现有的一个。检查查询是否返回正确的数据或数据库中正确更改的数据。使用数据单元或类似的东西

句法有效性肯定不是唯一的标准吗?你需要确认这个查询实际上会返回你需要的结果。我同意。在这种情况下,我只担心更新,因此不需要验证结果(更新的行数)。请检查整个问题,因为您所述的第二点并不完全适用。关于第一点(实现而不是行为),我不同意:这个类的最终目标是向数据库输出,我的问题是讨论检查这个输出的正确方法。我看到您的建议是使用真实数据库将单元测试升级为集成测试。因为这个类代表数据库集成,所以这可能是我所理解的最好的方法之一。我可能会尽量避免在我的测试中使用太多的数据库数据,但是在考虑使用集成部分时会使用。由于我的update和select语句是ANSI(针对PostgreSQL数据库运行),因此我可以使用嵌入式