我正在使用 Symfony2 设计一个小型应用程序,并将 DDD 域设想为供应商。这允许我通过不对使用它的内容做出任何假设来抽象我的域。基本上,这个域是一组执行其内部事务的业务实体和服务。通过简单的外观从外部(Symfony控制器)调用业务操作,这些操作不会暴露域中的任何内容。
现在,我想测试我的域以验证其业务规则。鉴于该域无法自行运行,因为它需要具体的存储库实现,因此我将测试设置为使用这些存储库的模拟。我的问题是:如何验证内部执行的所有域操作?
例如,假设我的域名由两个实体组成:Article
和Category
。我可以遍历一篇文章来获得它的类别,但我不能遍历一个类别来获取它的文章,因为它在我的域的上下文中没有意义。现在,我有一个业务规则,声明每当禁用某个类别时,此类别上的所有文章也应被禁用。
此操作的入口点是disable($category)
服务上的CategoryFacade
方法。此操作将首先禁用该类别,然后获取此类别的所有文章并禁用它们。
如果我从测试用例中调用disable()
操作,我可以验证我的类别是否已正确禁用,因为它是我执行测试的实际对象。但文章怎么样?我的类别上没有getArticles()
方法,并且由于我的域只使用模拟作为存储库,因此手动获取文章并对其进行断言是没有任何意义的。
修改
下面提出的答案提醒我一些关键的事情。实际上,在我的例子中,一个类别被认为是一个AR,因为它存在于文章范围之外。但由于文章也是AR,因此它应该对其自身的一致性负全部责任。这意味着,与类别相关联的所有文章的停用不应由类别服务启动,因为此服务不应该对文章有任何了解。我的选择将是下面提出的:在禁用类别时调度事件,并对我文章边界内的服务中的文章执行停用。
答案 0 :(得分:1)
首先,最好不要使用域逻辑来测试存储库,因为存储库应仅在应用层中使用,然后您应该测试应用程序服务。如果必须,那么只需创建一些测试存储库(基于内存)。 您应该仅在域对象上测试业务规则。例如,如果您想测试用户评级是否正常,请执行以下操作:
rated_user = UserFactory(parameters)
assertEqual(rated_user.rating, Rating(0))
rating_user = UserFactory(parameters)
rating_value = 3
rating_user.rateUser(rated_user, rating)
assertEqual(rated_user.rating, Rating(3))
对您的案例进行测试很困难,因为AR应该在不同的事务中更改(可能甚至不在同一个请求中)。根据你的说法,似乎Category应该是AR(聚合根),因为为了禁用类别,我们必须获取一个类别而不使用文章来执行此操作。 现在,当您禁用类别时,您应该发送文章应该获取的事件然后自行禁用。您可以通过调用EventListener回调测试文章是否被禁用,这将是更好的恕我直言。测试两个AR togheter实际上是一个集成测试,需要更多的设置。
无论如何,为了测试给定类别的所有文章是否都被禁用,你必须获取它们,可能使用类似" articlesRepository.getArticlesOfCategory(category)"如果它被禁用,请逐一检查。没有其他办法。