Вопрос

У нас есть требование добавить напоминание о событии, когда пользователь вводит свой адрес электронной почты на странице мероприятия.Событие — это еще один объект домена.Нашей первоначальной мыслью было создать объект домена 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.Затем вы можете проверить на макете объекта 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);
}

Другие советы

Мысли об API CustomerService

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

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

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

public void AddEventReminder(Customer customer, int eventId)

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

public void AddEventReminder(Customer customer, Event event)

Вопрос теперь в том, добавляет ли этот метод вообще какую-либо ценность?

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

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

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

Если вы сделаете Event корневым, это будет означать, что у вас не может быть CustomerRepository, и единственный способ получить, отредактировать и сохранить Customer — через Event.Для меня это звучит очень неправильно.

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top