Unit testing domain objects

aggregateroot, domain-driven-design, moq, unit-testing

Solution

In cases like this I would create a protected method in the service that creates the customer, in the test override that method it with anonymous inner class, and make it return a mock Customer object. Then you can verify on the mock Customer object that AddEmailReminder was called. Something like:

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

and in the test (assume limited C# knowledge, but it should illustrate the point):

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

Problem

We have a requirement to add an event reminder when a user enters their email address on an event page. Event is another domain object. Our initial thought was to create a Customer domain object and related CustomerService: ``` public class CustomerService { public void AddEventReminder(string emailAddress, int eventId) { var customer = new Customer(emailAddress); customer.AddEmailReminder(eventId); } } ``` How can we verify in a unit test that the AddEmailReminder method was indeed called on the new customer? My thoughts: - Use a factory to create the customer. This smells because I thought you were only supposed to use factory where there was some complexity in the object creation. - Bad code. Maybe there is a better way to do this? - Moq magic. On a separate note (maybe it is related), how do we decide which is the aggregate root here? We have arbitrarily decided the customer is, but it could equally be the event. I have read and understand articles on aggregate roots, but it is unclear in this scenario.

Original source