3

当用户在事件页面上输入他们的电子邮件地址时,我们需要添加事件提醒。事件是另一个域对象。我们最初的想法是创建一个 Customer 域对象和相关的 CustomerService:

public class CustomerService {
    public void AddEventReminder(string emailAddress, int eventId) {
       var customer = new Customer(emailAddress);
       customer.AddEmailReminder(eventId);
    }
}

我们如何在单元测试中验证 AddEmailReminder 方法确实被新客户调用了?

我的想法:

  1. 使用工厂来创造客户。这闻起来很臭,因为我认为您只应该在对象创建有一些复杂性的情况下使用工厂。
  2. 错误的代码。也许有更好的方法来做到这一点?
  3. 起订量魔法。

在单独的注释中(也许它是相关的),我们如何确定这里的聚合根?我们已经武断地决定了客户是,但它同样可能是事件。我已阅读并理解有关聚合根的文章,但在这种情况下尚不清楚。

4

2 回答 2

6

在这种情况下,我将在创建客户的服务中创建一个受保护的方法,在测试中使用匿名内部类覆盖该方法,并使其返回一个模拟客户对象。然后您可以在模拟客户对象上验证是否调用了 AddEmailReminder。就像是:

public class CustomerService {
    public void AddEventReminder(string emailAddress, int eventId) {
       var customer = createCustomer(emailAddress);
       customer.AddEmailReminder(eventId);
    }

    protected Customer createCustomer(string emailAddress) {
       return new Customer(emailAddress);
    }
}

并在测试中(假设 C# 知识有限,但应该说明这一点):

void testCustomerCreation() {
    /* final? */ Customer mockCustomer = new Customer("email");
    CustomerService customerService = new CustomerService() {
       protected Customer createCustomer(string emailAddress) {
           return mockCustomer;
       }            
    };

    customerService.AddEventReminder("email", 14);

    assertEquals(mockCustomer.EventReminder() /* ? */, 14);
}
于 2010-01-06T18:53:14.707 回答
2

关于 CustomerService API 的思考

您决定将此操作封装在 CustomerService 中是否有任何特殊原因?这对我来说看起来有点贫血。它可以直接封装在客户身上吗?

也许您遗漏了一些 CustomerService 代码示例以简化事情......

但是,如果必须,将签名更改为采用 Customer 实例可以解决问题:

public void AddEventReminder(Customer customer, int eventId)

但话又说回来,一个 Int32 几乎没有资格作为域对象,所以签名真的应该是

public void AddEventReminder(Customer customer, Event event)

现在的问题是这种方法是否增加了任何价值?

哪个是聚合根?

他们都没有,我想。聚合根表示您通过根管理子项,在这种情况下,这两种方式都没有意义。

考虑以下选项:

如果您将 Event 设为根,则意味着您可能没有 CustomerRepository,并且您可以检索、编辑和保留 Customer 的唯一方法是通过 Event。这对我来说听起来很不对劲。

如果您将 Customer 设置为根,则您可以没有 EventRepository,并且您可以检索、编辑和持久保存 Event 的唯一方法是通过特定的 Customer。这听起来对我来说同样错误。

The only remaining possibility is that they are separate roots. This also means that they are only loosely connected to each other, and that you will need some kind of Domain Service to look up Events for a Customer, or Customers for an Event.

于 2010-01-07T08:23:05.840 回答