首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >TDD + DDD:模型抽象

TDD + DDD:模型抽象
EN

Stack Overflow用户
提问于 2020-08-15 18:19:33
回答 4查看 193关注 0票数 2

我最近有一次有趣的经历,但到目前为止还没有找到一个令人满意的答案:我是DDD的铁杆粉丝,并试图定义具有行为和良好信息隐藏的富领域对象,即使团队正式没有实践DDD。归根结底,这并不重要,因为您有一个定义良好的对象,该对象表示问题域中的某些内容。

也就是说,我也想更多地练习TDD。不幸的是,如果我测试一个使用这种富领域模型的服务,这些模型通常不是抽象的。因此,为了测试服务的行为,我还需要设置模型。这个模型有它自己的不变量等,因此在每次服务测试时,我也会测试服务正在使用的模型。

这似乎是一个很大的禁忌,因为我不仅“不是真正的单元测试”,而且设置测试也很麻烦,因为排列代码变得很大。在我看来,除了开始为模型创建接口之外,似乎别无选择。但似乎我是唯一这么想的人。例如,这里有一篇很大的文章,为什么这是一个反模式:https://lostechies.com/jamesgregory/2009/05/09/entity-interface-anti-pattern/

我也不太乐于为所有模型创建接口,因为它们应该真正表示一些东西,仅仅为了测试而添加另一层抽象层似乎有点过头了。也就是说,最好的解决方案是什么?将DDD和TDD结合在一起的赛场上的人们是如何处理这一问题的?

EN

回答 4

Stack Overflow用户

发布于 2020-08-16 02:01:25

这似乎是一个很大的禁忌,因为我不仅“不是真正的单元测试”,而且设置测试也很麻烦,因为排列代码变得很大。

我认为你可以忽略“不是真正的单元测试”;重要的是使用适合于目的的工具,而不是品牌。

也就是说,troublesome to set up the tests是一个合理的关注点,而且它本身就有足够的理由来寻找改进设计的方法。

如果您的服务与某些第三方实现紧密耦合,没有提供替代成本,那么您将如何将其从测试中解耦?通常的答案是在你的代码和第三方代码之间引入一种新的设计元素-- seam。

seam的两个重要特征:

  • 它提供了替换,也就是说,你有一个接口。
  • 集成了第三方代码的接口的实现是“如此简单,显然没有接口”

然后,在您的测试中,引入替代实现。

你的“域模型”的游戏是完全相同的。假设您正在应用通常的生命周期模式,seam包含一个存储库的替代品和一个聚合根实体的替代品。

一些好消息-你只需要隐藏整个聚合:只需要你的服务关心的接口部分。实际上,您所做的就是为每个服务定义描述您的服务和域模型之间交互的契约。“角色接口”在这里将是一个有用的搜索词。

票数 2
EN

Stack Overflow用户

发布于 2020-08-16 13:58:42

首先,我将确保满足这两个条件:

  • 域模型是POJO
  • 域层隔离(其他层可以访问域层,但不能访问域层)

然后,可以使用工厂、生成器或TestHelpers将模型带到所需的状态以进行测试。

票数 2
EN

Stack Overflow用户

发布于 2020-08-15 23:09:56

基础知识

测试作用域

测试单元Testing

  • Integration

领域模型

  • 这些应该是单元测试,用来测试域模型/聚合的方法。

服务

  • 这些应该是集成测试,用于测试服务方法和关联模型的集成。

My Broad

当您测试域模型时,可能会有许多差异,您需要在单元测试中说明这些差异。

当这些转化为在集成测试中使用的需求时,我倾向于为您的域模型使用某种CreationFactory (或ArrangementFactory)。

然后,您可以在这两组测试中使用它们。

举个例子。

代码语言:javascript
复制
public class ArrangeUser {
  public static User ArrangeStandardUser() {
    return new User(...standard...);
  }

  public static User ArrangeAdminUser() {
    return new User(...admin...);
  }
}

然后在你的单元测试中...

代码语言:javascript
复制
// Arrange
User standardUser = ArrangeUser.StandardUser();

// Act
bool canDoSomething = standardUser.CanDoSomething();

// Assert
Assert.True(canDoSomething);

然后在你的集成测试中...

代码语言:javascript
复制
// Arrange
User standardUser = ArrangeUser.StandardUser();
ServiceToTest service = new ServiceToTest(standardUser); // replace with some sort of Repository Mock or whatever suits.

// Act
var bool canDo = service.CanDoService();

// Assert
Assert.True(canDo);

通过这种方式,您可以测试单元方面和服务方面-通过创建一种通用的方法来创建安排,而不必抽象出实体并一遍又一遍地解决重新创建相同事物的问题。

注意:这只是一个基本的代码演示,可以根据场景或您首选的测试风格进行更复杂的演示。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/63424912

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档