应用CQRS - 单元测试薄读层是否必要?

17
考虑到一些实施CQRS的建议主张相当接近底层的查询实现,例如直接使用ADO.NET查询数据库(或基于LINQ的ORM),那么尝试对它们进行单元测试是否会是一个错误?我想知道是否真的有必要这样做?
我的想法是:
1.提供可模拟的“轻量级读取层”所需的额外架构复杂性似乎与将架构仪式保持到最低限度的建议相反。
2.为有效地覆盖用户可能组成的每个查询角度需要大量的单元测试。
具体来说,我正在尝试在ASP.NET MVC应用程序中使用CQRS,并想知道是否要费心单元测试控制器操作方法,还是只测试领域模型即可。
非常感谢。

覆盖用户可能构建的每个查询角度所需的单元测试数量是可怕的。你能解释一下吗?为什么用户会自己创建查询?你的查询端应该是限制这一点的,然后你可以测试你的查询/视图服务(如果你真的需要减少你的视图范围)。 - roundcrisis
也许你应该开始考虑并确定用户实际需要的范围,而不是承诺完全自由。 - Yves Reynhout
单元测试可能看起来很重复,不划算,如果你住在欧洲或美国,... - Yves Reynhout
1
告诉Yves,“也许你应该开始考虑和限定用户实际需要的范围,而不是承诺完全自由。” - 去告诉谷歌吧... - Neil Barnwell
你还没有理解...不要混淆搜索和薄读层。 - Yves Reynhout
5个回答

7

根据我的经验,如果你正在创建一个良好的去规范化读取模型,那么90%-99%的读取操作不需要编写单元测试。

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


7

我同意您的观点,对于这种类型的代码进行单元测试可能没有太多好处。但是还有一些有用的测试方法。

如果您正在执行用户读取查询参数的验证,则需要测试无效的请求参数是否会抛出适当的异常,并允许有效参数。

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

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


2
正如你可能已经知道的那样,单元测试不仅仅是关于代码覆盖率和预防错误,更重要的是好的设计。虽然我在匆忙时经常跳过测试读取模型事件处理程序,但毫无疑问,出于所有代码都应该进行TDD的原因,应该对其进行测试。
我也没有对我的HTTP操作进行单元测试(我没有控制器,因为我使用的是Nancy而不是.NET MVC)。
这些是集成点,不倾向于包含太多逻辑,因为大部分逻辑都封装在命令处理程序和领域模型中。
我认为很容易不去测试这些的原因是它们非常简单和重复,对于事件到读取模型的去规范化几乎没有深入思考。对于我的HTTP处理程序也是如此,它们基本上只是处理请求并向域发出命令,并具有一些基本逻辑来返回响应给客户端。
在开发时,我经常在这段代码中犯错,如果我使用TDD,我可能会犯少得多的这些错误,但这也需要更长的时间,而且这些错误往往很容易被发现和修复。
我的直觉告诉我我还是应该在这里应用TDD,因为它仍然非常松散耦合,而且编写测试不应该很难。如果你发现很难编写测试,那可能就表明你的控制器存在代码异味。

1

我见过这种单元测试的方式是在数据库中创建一组事物,运行单元测试,然后清除创建的事物。

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

这些单元测试非常有用,并捕获了许多与数据库交互相关的错误。


1
谢谢您的建议,但那不是严格的单元测试,那是集成测试。在我的开发机器上,我不想为此增加额外负担。 - Neil Barnwell

0
在我的asp.net mvc应用程序中,我也应用了sqrc。但是,我们使用文档数据库(mongodb)而不是sql和“ADO.NET查询”或“Linq”,并且每个命令或事件处理程序直接更新数据库。
我为一个命令/事件处理程序创建了一个测试。经过100%的单元测试,我知道我的域在95%的情况下工作正常。但是对于操作/控制器/用户界面,我应用了ui测试(使用selenium)。
因此,似乎域(命令/事件处理程序和直接更新到数据库)和ui测试都是您的“集成测试”。
我认为您至少应该测试域部分,因为所有逻辑都封装在命令/事件处理程序中。
FYI:我还从实体框架开始开发域部分,然后通过存储过程直接更新到数据库,但是使用文档数据库真的很高兴。我尝试了一些不同的文档数据库,但mongodb看起来最适合我。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接