16

鉴于实现 CQRS 的一些建议提倡相当接近金属查询实现,例如直接针对数据库的 ADO.NET 查询(或者可能是基于 LINQ 的 ORM),尝试和单元测试是否是错误的他们?

我想知道它是否真的有必要?

我对此事的看法:

  1. 提供可模拟的“细读层”的额外架构复杂性似乎与将架构仪式保持在最低限度的建议的本质相反。
  2. 有效覆盖用户可能编写的每个查询角度的单元测试数量是可怕的。

具体来说,我正在一个 ASP.NET MVC 应用程序中尝试 CQRS,我想知道是否需要对我的控制器操作方法进行单元测试,或者只是测试域模型。

提前谢谢了。

4

5 回答 5

6

根据我的经验,如果您正在创建一个很好的非规范化读取模型,您将执行 90%-99% 的读取操作,不要保证围绕它们进行单元测试。

我发现对 CQRS 应用程序进行 TDD 最有效和最高效的方法是编写将命令推送到您的域中的集成测试,然后使用查询从数据库中获取数据以进行断言。

于 2011-03-03T22:30:50.747 回答
5

我倾向于同意您的观点,即对这种代码进行单元测试并不是那么有益。但是仍然有一些有用的测试空间。

您必须对用户读取的查询参数进行一些验证,如果是这样,则测试无效的请求参数是否会引发合适的异常,并且允许有效参数。

如果您使用的是 ORM,我发现成本/收益比对于测试映射代码来说太高了。假设您的 ORM 已经过测试,映射中可能存在错误,但您很快就会找到并修复它们。

我还发现编写一些集成测试(使用相同的测试框架)很有用,只是为了确保我可以连接到数据库,并且 ORM 配置不会引发任何映射异常。您当然不想编写查询实际数据库的单元测试。

于 2011-02-25T10:57:06.253 回答
2

正如您可能已经知道的那样,单元测试与其说是关于代码覆盖率和防止错误,不如说是关于良好的设计。虽然我经常在匆忙时跳过测试读取模型事件处理程序,但毫无疑问,由于代码应该是 TDD 的所有原因,它可能应该完成。

我也没有对我的 HTTP 操作进行单元测试(我本身没有控制器,因为我使用的是 Nancy 而不是 .NET MVC)。

这些是集成点,往往不包含太多逻辑,因为其中大部分都封装在命令处理程序和域模型中。

我认为不测试这些是相当容易的原因是因为它们非常简单且非常重复,在将事件非规范化到读取模型方面几乎没有深入思考。我的 HTTP 处理程序也是如此,它几乎只是处理请求并向域发出命令,并带有一些用于向客户端返回响应的基本逻辑。

在开发过程中,我经常在这段代码中犯错误,如果我使用 TDD,这些错误可能会少得多,但它也会花费更长的时间,而且这些错误往往很容易发现和修复。

我的直觉告诉我,我仍然应该在这里应用 TDD,它仍然是非常松散耦合的,编写测试应该不难。如果您发现很难编写可能表明控制器中有代码异味的测试。

于 2011-02-27T21:05:20.003 回答
1

我见过类似这种单元测试的方法是让单元测试在数据库中创建一组东西,你运行你的单元测试,然后清理创建的东西。

在过去的一项工作中,我看到这个设置非常好,使用数据结构来描述对象及其关系。这是通过 ORM 运行以创建具有这些关系的对象、用于查询的数据,然后使用 ORM 删除对象。为了使单元测试更容易设置每个类指定的默认值,以便在没有覆盖这些值的单元测试中使用。然后单元测试中的数据结构只需要指定非默认值,这使得单元测试的设置更加紧凑。

这些单元测试非常有用,并在数据库交互中发现了许多错误。

于 2011-02-02T01:19:17.343 回答
0

在我的一个 asp.net mvc 应用程序中,我还应用了 sqrc。但是我们使用文档数据库(mongodb)和每个命令或事件处理程序直接更新数据库,而不是 sql 和“ADO.NET 查询”或“Linq” 。

我已经为一个命令/事件处理程序创建了一个测试。在 100% 的单元测试之后,我知道我的域工作 95% 正确。但是对于动作/控制器/ui,我已经应用了 ui 测试(使用selenium)。

因此,似乎域的单元测试(命令/事件处理程序和直接更新数据库)和 ui 测试它的“集成测试”。

我认为您至少应该测试域部分,因为您的所有逻辑都封装在命令/事件处理程序中。

仅供参考:我也开始从实体框架开始开发域部分,而不是通过存储过程直接更新到数据库,但对文档数据库非常满​​意。我尝试了一些不同的文档数据库,但 mongodb 看起来最适合我。

于 2011-02-02T23:14:31.960 回答