应用CQRS - 是否需要对薄读取层进行单元测试?

时间:2011-02-02 00:41:52

标签: c# .net asp.net-mvc unit-testing cqrs

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

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

我对此事的看法:

  1. 提供可模拟的“精简阅读层”的额外架构复杂性似乎与建筑仪式的最低限度相反。
  2. 有效覆盖用户可能构成的每个查询角度的单元测试数量是可怕的。
  3. 具体来说,我正在ASP.NET MVC应用程序中尝试CQRS,并且想知道是否要单独测试我的控制器操作方法,或者只是测试域模型。

    非常感谢提前。

5 个答案:

答案 0 :(得分:4)

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

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

如果你正在使用ORM,我发现测试映射代码的成本/效益比太大了。假设您的ORM已经过测试,映射中可能存在错误,但您很快就会发现并修复它们。

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

答案 1 :(得分:3)

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

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

答案 2 :(得分:2)

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

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

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

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

在开发时,我经常在这段代码中犯错误,如果我使用TDD,我可能会减少这些错误,但这也需要更长的时间,这些错误往往很容易被发现和修复。 / p>

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

答案 3 :(得分:1)

我看到像这个单元测试过的方法是让单元测试在数据库中创建一组东西,运行单元测试,然后清理创建的东西。

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

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

答案 4 :(得分:0)

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

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

所以似乎域的单元测试(命令/事件处理程序和数据库的直接更新)和ui测试它是'集成测试'。

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

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