在执行DDD时是否应该模拟实体和值对象?


9

阅读后 文章Newable VS 注射对象以及如何将这些概念涉及到DDD的服务,实体和值对象,我留下了有关使用我的代码newables尤其是在我的单元测试的一些疑虑。

可更新项的主要候选对象是Entities和Value对象,这意味着与其将这些依赖项注入其他对象中,还应该只是new这些对象的一个​​实例,并直接在代码中使用它们。

但是,良好的DDD做法主张将责任分配给实体和价值对象(如果认为合适的话)。因此,实体和价值对象将最终在其中包含一些严肃的业务逻辑。

现在,如果服务在实体或值对象上运行,我应该模拟该实体或值对象并将该模拟传递给该服务(模拟将要求interface对似乎被提倡的价值对象或实体使用)?

还是我应该只是new一个实体/值对象,并将具体实现传递给服务,从而违反仅测试一个单元的单元测试原理?



这取决于您是古典测试员还是模拟测试员:martinfowler.com/articles/mocksArentStubs.html
jhewlett

@jhewlett古典主义者不会嘲笑任何东西。嘲笑者很可能只会嘲笑服务,存储库和工厂(它们是“可注入的”),而不会嘲笑实体或价值对象(它们是“可更新的”)。
罗杰里奥

@Rogério,当您说服务时;您是指应用程序服务还是域服务?
w0051977

@Songo,您决定了什么?您是否嘲笑:实体;价值对象和领域服务?
w0051977

Answers:


11

我读到您认为单元测试,就像SOLID对象一样,必须有“一个打破的理由”。这是一个崇高的目标,但我认为您会发现在许多情况下这根本不可行。其中一种情况是,您有一个“丰富”域对象(DDD在实体和值对象之间进行区分,它们都包含“域模型”),它是被测系统的依赖项。

在这种情况下,我有,哲学给出域对象具有其自己的全面的单元测试范围,相信该对象将针对不同的SUT进行单元测试中设计的工作并不一定违反单元测试。如果此测试由于域的重大更改而中断,那么我希望域对象的单元测试也将中断,从而使我朝着需要调查的方向发展。如果域对象的单元测试已正确更新为红色测试,则更改后变为绿色,而另一个测试失败了,那也不一定是一件坏事。这意味着该另一个测试的期望与对该领域的新期望相冲突,并且我需要确保它们彼此一致以及系统的总体接受标准。

这样,如果域对象产生的“副作用”从单元测试的角度来看是不希望的(即接触诸如数据存储之类的外部资源),或者域对象的逻辑足够复杂以至于无法模拟域对象,则仅对域对象进行模拟将其置于适当的测试状态成为定义和通过测试的障碍。

然后,这成为一个驱动问题。哪个更容易?要将领域对象用于测试中的预期目的还是对其进行模拟?做任何更容易的事情,直到不再是更简单的选择为止,例如当功能更改以复杂的方式破坏了对服务的测试时;如果发生这种情况,则重写测试以生成一个模拟,该模拟可以暴露服务所依赖的功能要求,而不会破坏该服务的复杂性。

理解无论哪种方式,都应该有一个集成测试,该测试使用插入到真实服务中的真实域对象,以更高的抽象级别测试这两者之间的交互(例如,不仅测试服务背后的功能,终结点,但代理是域对象的序列化和发送)。


在DDD中,“域模型”还包括域服务,存储库和工厂,而不仅仅是实体和值对象。
罗杰里奥

0

信任依赖类,它可以正常工作,希望当某些东西不起作用时,它将在某些单元测试中失败,那么应该对此进行非常好的测试。也许缺少一些重要的单元测试?可能存在未经测试的情况,这会产生错误,该错误将在我的原始测试类中产生,而不会在依赖类本身中捕获。

因此,在我看来,对于单元测试,应该模拟依赖类。如果不这样做,那么它就是一个集成测试。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.