当前位置: 首页 > 编程语言 > C#

TDD、DDD和封装共享

时间:2023-04-11 02:59:31 C#

TDD、DDD和封装在我的工作场所遵循“架构师”传下来的错误实践几年后,我认为一定有更好的方法,我一直最近阅读有关TDD和DDD,我认为原则和实践将非常适合我们编写的软件的复杂性。但是,我见过的许多TDD示例都在域对象上调用方法,然后测试该对象的属性以确保行为正确执行。另一方面,业内几位受人尊敬的人(GregYoung最著名的是他对CQRS的讨论)提倡通过删除所有“getter”来完全封装每个域对象。所以,我的问题是:如果禁止检索域状态,我该如何测试域对象的功能?我确定我遗漏了一些基本的东西,所以请随时称我为白痴并启发我-任何指导将不胜感激。您所描述的是状态验证,您可以在其中断言域对象的状态。TDD的一个分支称为行为验证,它使用Mock对象。行为验证允许您指定应调用哪些方法,以及如果需要,不应调用哪些方法。查看MartinFowler的这篇文章了解更多详细信息:Mocksarenotstubs。好的,这个答案晚了一年;-)但是当您想测试CQRS模型时,您可以对触发的域事件而不是实体状态进行断言。例如,如果您想测试调用:customer.Rename("Foo")是否会产生正确的行为。不是测试customer.Name是否等于“foo”,而是测试未决事件存储中是否存在值为“Foo”的未决CustomerRename事件。(在你的uow中或在你的实体事件列表中取决于实现)如果你真的要禁止检索状态那么你将仅限于行为测试,可能通过像TypeMock这样的模拟框架,它能够跟踪你的行为目的。如果你可以做纯BDD,那么理论上你可以通过它的行为方式断言整个系统的正确性。在实践中,我发现在许多情况下,BDD比仅状态测试更脆弱。虽然有些人可能会主张某种理论,但只有当它对你有用时它才有效。基于状态的测试仍然占我们编写的所有单元测试的90%,并且我们在我们的团队中非常了解BDD。做最适合你的事情。问题。首先,当您执行诸如TDD之类的操作以使您的代码可测试时,您最终会得到更小的类。如果你有一个类有很多你无法检查的私有属性,它很可能会被分成多个类并且更容易测试。其次,老派的OO架构试图通过使用语言保护来防止软件被访问来确保软件安全。TDD体系结构通过编写验证代码实际运行的测试来使软件更加健壮,而不那么强调使用语言结构来确保程序不执行的操作。最后,检查属性并不是您的验证代码执行它应该执行的操作的唯一方法。xUnit设计模式一书记录了其他方法:http://xunitpatterns.com/Result%20Verification%20Patterns.html我调用系统的公共输入方法(即我将输入数据推送到系统中),然后我得到(并断言)系统输出。我不测试系统的内部状态,而是测试它的公共/可见行为:我应该测试内部实现,还是只测试公共行为?你提到了状态测试。还有行为测试。用于此的技术是依赖注入、控制反转和模拟:类的所有副作用都实现为对其“依赖项”的方法调用——即从外部提供的对象,通常在构造函数中。然后,在您的单元测试中,您提供假对象而不是真实对象。假对象可以记住它是否调用了某个方法,这就是您在测试中断言的内容。存在许多模拟框架,它们通过动态生成实现给定接口的类来自动创建模拟对象。最受欢迎的是Rhino.Mocks和Moq。嘿贾斯汀,和你一样,我最近考虑将getter添加到我的只写域对象以进行单元测试,但现在我确信我错了。假设你首先想到了一个只写字段的想法,那么如果你有getters,你就有麻烦了。只写域原则要求您从域对象触发事件,或从域对象写入的投影中读取,或类似的东西。一旦公开了getter,就开始公开对象的“形状”,正如GregYoung所说,“领域对象具有行为,而不是形状”。话虽如此,我正在为同样的问题而苦苦挣扎......你如何对只写域对象进行单元测试?这是我目前的计划:我正在考虑让我的领域对象触发一个领域事件,说“这些属性已更改”,并且在我的单元测试中我会在发送“EditCommand”之前注册它。查看UdiDahan关于域事件的帖子,还可以查看EricEvans关于域事件的帖子。在我最终偶然发现以下文件之前,我一直在想同样的事情。我发现它们是执行行为验证的优秀介绍,尤其是第一个为我提供了一些“顿悟时刻”:以上是C#学习教程的全部内容:TDD、DDD和封装分享,如果是对大家有用并且需要了解更多C#学习教程,希望大家多多关注—使用模拟和测试设计基于角色的对象模拟角色,而不是对象如转载请注明出处: