質問

ユーザーがイベント ページに電子メール アドレスを入力したときにイベント リマインダーを追加するという要件があります。イベントは別のドメイン オブジェクトです。私たちの最初の考えは、Customer ドメイン オブジェクトと関連する CustomerService を作成することでした。

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

AddEmailReminder メソッドが新規顧客に対して実際に呼び出されたことを単体テストで検証するにはどうすればよいでしょうか?

私の考え:

  1. ファクトリーを使用して顧客を作成します。これは、オブジェクトの作成が複雑な場合にのみファクトリーを使用する必要があると考えていたため、臭いがします。
  2. 悪いコードです。おそらくこれを行うためのより良い方法があるでしょうか?
  3. モックマジック。

別の話になりますが (関連しているかもしれません)、ここでどれが集約ルートであるかをどのように決定するのでしょうか?私たちは顧客を恣意的に決定しましたが、同様にイベントである可能性もあります。集約ルートに関する記事を読んで理解しましたが、このシナリオでは不明です。

役に立ちましたか?

解決

このようなケースでは、私は匿名の内部クラスを使用してテストオーバーライドメソッドそれで、顧客を作成し、サービスで保護されたメソッドを作成し、それはモックCustomerオブジェクトを返すことになるだろう。そして、あなたはAddEmailReminderが呼び出されたモックCustomerオブジェクト上で確認することができます。 ような何かます:

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);
}

他のヒント

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 を経由することになります。それは私にとっても同じように間違っているように思えます。

残された唯一の可能性は、それらが別のルートであるということです。これは、それらが相互に緩やかに接続されているだけであり、顧客のイベント、またはイベントの顧客を検索するには、ある種のドメイン サービスが必要になることも意味します。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top