This post is related to the following ones

  1. Introduction to CQRS
  2. Testing the domain
  3. Modeling behavior
  4. Implementing an aggregate root

In one of my previous post I explained the testing benefits of the CQS architecture.

  • I arrange my tests by replaying a set of events.
  • I act by executing a set of commands.
  • And I assert by comparing the events published by the aggregate root to the events I expected to be published.

I am doing Act-Arrange-Assert testing in the simplest most readable way and at the same time creating business value.

In this post I will look at how I would implement my aggregate root to enable this kind of testing. What we need to look at is how the aggregate root implements the replaying of events. This is the key to loading the aggregate root into it’s current state.

The base class

In addition to managing it’s domain logic each aggregate root is responsible for

  • Keeping list of all the events that the aggregate root has published after it was loaded.
  • Maintaining a mapping between events and the methods for applying the events to the aggregate root.

When saving an aggregate root to the event store you would ask for the events that has been published since it was loaded. That is why we need to store this information. In a testing scenario it is also useful to be able to assert against the events published by the aggregate. For each event, the aggregate root has a method for applying that event. A dictionary of these event-method pairs is maintained by the aggregate root. These responsibilities are common for all aggregate roots, so we will put it in a base class. Before I elaborate on this base class (called HandlesEvents) lets look at an example.

The aggregate root

The aggregate root has a behaviour (i.e. method) that corresponds to a command. Given a ChangeDescriptionCommand coming from the UI you would typically have a ChangeDescription method on the aggregate root. In the command handler you would map a command to a behaviour on the aggregate root.

The implementation of a given behaviour is the key here. In a behaviour you would

  1. validate the input,
  2. create an event
  3. and call a method that applies the event to the aggregate root.

The ChangeDescription behaviour implementation would look something like this:

public class Foo:HandelsEvents {

  private string _description;
  
  public Foo(){
    RegisterHandler<ChangeDescriptionEvent>(applyChangeDescripionEvent);
  } 
      
  public void ChangeDescription(string description){
    if(description == null)
      throw new InvalidDescriptionException();

    ApplyEvent(new ChangeDescriptionEvent(description));
  }

  private applyChangeDescripionEvent(ChangeDescriptionEvent e) {
    _description = e.Description;
  }
}

When the ChangeDecription behaviour is called, the input is validated, the event is created and applied to the aggregate root. Notice I’m am calling the applyChangeDescriptionEvent method thru the base class in stead of calling it directly. This is to enable the base class to do some bookkeeping on what events are called and how they are applied to the aggregate root. Notice that we register the mapping between the event and the method in the constructor. This way the base class knows which method to call when applying the event, both when you are loading an aggregate root into it’s current state and when your applying the event thru a behaviour.

More on the base class

Now lets look at the base class HandlesEvents. The HandlesEvents base class is here for convenience. If I want to replay a set for events I will only need to call the method LoadFromHistory(IEnumerable<IEvent> history) on the HandlesEvent class. The HandlesEvent class will then get the aggregate root in the required state by applying the events to the appropriate methods.

public void LoadFromHistory(IEnumerable<IEvent> history)
{
  foreach(var e in history)
      ApplyEvent(e,false);
}

The ApplyEvent method finds the given handler method for the event and call this method with the event as an parameter. The boolean parameter false is an instruction to the ApplyEvent method not to keep a record of this event. We are only interested in the events that happend after the aggregate root was put in its current state. The ApplyEvent in the HandlesEvent base class will look something like this.

protected void ApplyEvent(IEvent e, bool add)
{
  AppliesEvent handler;

  if(!_lookUp.TryGetValue(e.GetType(), out handler))
    throw new HandlerNotFoundException();
  
  handler(e);

  if(add) _events.Add(e);
}

The HandelsEvents base class will also have a public method GetChanges to expose all the events that where published after the aggregate root was loaded into it’s initial state.

So lets sum up what we’ve got here.

  • You can load a set of events into your aggregate root to get it to the required state
  • You can invoke a behaviour on the aggregate root
  • You can get a list of events that the aggregate root has published

You are ready to start testing.

Should I go deeper into this stuff ? Was this post just confusing ? Is this English ? Hit me with a comment :)

    F Share