2010-01-06 7 views
3

У нас есть требование добавить напоминание о событии, когда пользователь вводит свой адрес электронной почты на странице событий. Событие - еще один объект домена. Наша первоначальная мысль была создать объект домена клиента и связанные с ними сервисными службами:Устройства для тестирования объектов домена

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

Как мы можем убедиться в модульном тесте, что метод AddEmailReminder действительно призвали новый клиент?

Мои мысли:

  1. Используйте завод, чтобы создать клиента. Это пахнет, потому что я думал, что вы должны использовать фабрику, где была какая-то сложность в создании объекта.
  2. Плохой код. Может быть, есть лучший способ сделать это?
  3. Moq магии.

Отдельная заметка (возможно, это связано), как мы решаем, какой из них является общим корнем? Мы произвольно решили, что клиент, но это может быть и событие. Я читал и понимаю статьи об общих корнях, но в этом сценарии неясно.

ответ

6

В таких случаях я бы создал защищенный метод в службе, которая создает клиента, в тесте переопределяет этот метод с анонимным внутренним классом и возвращает ему объект mock Customer. Затем вы можете проверить объект mock Customer, который был вызван 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); 
} 
2

Мысли о CustomerService API

Есть ли конкретные причины, по которым вы решили инкапсулировать эту операцию в CustomerService? Это выглядит немного Anemic для меня. Может ли он быть инкапсулирован непосредственно на клиента?

Возможно, вы оставили что-то из примера CustomerService кода, чтобы упростить вещи ...

Однако, если необходимо, изменение подписи взять экземпляр клиента решает проблему:

public void AddEventReminder(Customer customer, int eventId) 

но то опять же, Int32 вряд ли можно квалифицировать как объект домена, поэтому подпись должна быть действительно

public void AddEventReminder(Customer customer, Event event) 

вопрос теперь добавляет ли этот метод а ny значение вообще?

Каков совокупный корень?

Никто из них, я бы не подумал. Совокупный корень указывает, что вы управляете детьми только через корень, и это не имеет смысла в этом случае.

Рассмотрим варианты:

Если вы сделаете событие корень, это будет означать, что вы не могли бы не CustomerRepository, и единственный способ, которым Вы могли бы получить, редактировать и сохраняться Клиент будет через событие. Это звучит очень неправильно для меня.

Если вы создаете для Клиента корень, у вас не может быть EventRepository, и единственный способ получить, отредактировать и перенести событие будет через конкретного клиента. Это звучит так же неправильно для меня.

Единственная оставшаяся возможность состоит в том, что они являются отдельными корнями. Это также означает, что они только слабо связаны друг с другом и что вам потребуется какая-то служба домена для поиска событий для Клиента или Клиентов для события.

+0

. Весь смысл этого метода службы домена заключается в том, что он вызывается непосредственно из службы приложения, которая получила dto с адресом электронной почты и идентификатором события. Я решил, что объект домена должен иметь дело только с полными объектами, поэтому служба домена должна это обработать. Я не понимаю, почему это анемия означает, что он не должен идти на службу домена, если что-нибудь, я думаю, будет наоборот, поскольку объекты домена связаны с логикой. Re, совокупный корень, я согласен, что они оба являются совокупными корнями, вопрос, который я задавал, заключается в том, какой агрегированный корень отвечает за ассоциацию? – JontyMC

+0

... интересный ответ, хотя. Если я должен был изменить подпись, какой код будет отвечать за создание агрегатного корня клиента? Возможно, это более уместный вопрос. – JontyMC

+0

Я подозревал, что услуга должна была отобразиться из прикладного уровня. Однако в этом случае это не доменная служба - это служба уровня приложения и принадлежит к этому слою. В этом случае, я думаю, вам нужна абстрактная фабрика (возможно, CustomerRepository), которая может искать существующего клиента на основе адреса электронной почты. –

Смежные вопросы