@Test
  public void testLoadAndSaveAggregate() {
    UUID identifier = UUID.randomUUID();
    DomainEventMessage event1 =
        new GenericDomainEventMessage<String>(
            identifier, (long) 1, "Mock contents", MetaData.emptyInstance());
    DomainEventMessage event2 =
        new GenericDomainEventMessage<String>(
            identifier, (long) 2, "Mock contents", MetaData.emptyInstance());
    when(mockEventStore.readEvents("test", identifier))
        .thenReturn(new SimpleDomainEventStream(event1, event2));

    TestAggregate aggregate = testSubject.load(identifier, null);

    assertEquals(0, aggregate.getUncommittedEventCount());
    assertEquals(2, aggregate.getHandledEvents().size());
    assertSame(event1, aggregate.getHandledEvents().get(0));
    assertSame(event2, aggregate.getHandledEvents().get(1));

    // now the aggregate is loaded (and hopefully correctly locked)
    StubDomainEvent event3 = new StubDomainEvent();

    aggregate.apply(event3);

    CurrentUnitOfWork.commit();

    verify(mockEventBus).publish(isA(DomainEventMessage.class));
    verify(mockEventBus, never()).publish(event1);
    verify(mockEventBus, never()).publish(event2);
    verify(mockEventStore, times(1)).appendEvents(eq("test"), isA(DomainEventStream.class));
    assertEquals(0, aggregate.getUncommittedEventCount());
  }
  @Test
  public void testLoadEventsWithDecorators() {
    UUID identifier = UUID.randomUUID();
    SpyEventPreprocessor decorator1 = new SpyEventPreprocessor();
    SpyEventPreprocessor decorator2 = new SpyEventPreprocessor();
    testSubject.setEventStreamDecorators(Arrays.asList(decorator1, decorator2));
    when(mockEventStore.readEvents("test", identifier))
        .thenReturn(
            new SimpleDomainEventStream(
                new GenericDomainEventMessage<String>(
                    identifier, (long) 1, "Mock contents", MetaData.emptyInstance()),
                new GenericDomainEventMessage<String>(
                    identifier, (long) 2, "Mock contents", MetaData.emptyInstance()),
                new GenericDomainEventMessage<String>(
                    identifier, (long) 3, "Mock contents", MetaData.emptyInstance())));
    TestAggregate aggregate = testSubject.load(identifier);
    // loading them in...
    InOrder inOrder = Mockito.inOrder(decorator1.lastSpy, decorator2.lastSpy);
    inOrder.verify(decorator2.lastSpy).next();
    inOrder.verify(decorator1.lastSpy).next();

    inOrder.verify(decorator2.lastSpy).next();
    inOrder.verify(decorator1.lastSpy).next();

    inOrder.verify(decorator2.lastSpy).next();
    inOrder.verify(decorator1.lastSpy).next();
    aggregate.apply(new StubDomainEvent());
    aggregate.apply(new StubDomainEvent());
  }
  @Test
  public void testLoadAndSaveWithConflictingChanges() {
    ConflictResolver conflictResolver = mock(ConflictResolver.class);
    UUID identifier = UUID.randomUUID();
    DomainEventMessage event2 =
        new GenericDomainEventMessage<String>(
            identifier, (long) 2, "Mock contents", MetaData.emptyInstance());
    DomainEventMessage event3 =
        new GenericDomainEventMessage<String>(
            identifier, (long) 3, "Mock contents", MetaData.emptyInstance());
    when(mockEventStore.readEvents("test", identifier))
        .thenReturn(
            new SimpleDomainEventStream(
                new GenericDomainEventMessage<String>(
                    identifier, (long) 1, "Mock contents", MetaData.emptyInstance()),
                event2,
                event3));
    testSubject.setConflictResolver(conflictResolver);
    TestAggregate actual = testSubject.load(identifier, 1L);
    verify(conflictResolver, never())
        .resolveConflicts(anyListOf(DomainEventMessage.class), anyListOf(DomainEventMessage.class));
    final StubDomainEvent appliedEvent = new StubDomainEvent();
    actual.apply(appliedEvent);

    CurrentUnitOfWork.commit();

    verify(conflictResolver)
        .resolveConflicts(payloadsEqual(appliedEvent), eq(Arrays.asList(event2, event3)));
  }
  @Test
  public void testLoadWithConflictingChanges_NoConflictResolverSet() {
    UUID identifier = UUID.randomUUID();
    DomainEventMessage event2 =
        new GenericDomainEventMessage<String>(
            identifier, (long) 2, "Mock contents", MetaData.emptyInstance());
    DomainEventMessage event3 =
        new GenericDomainEventMessage<String>(
            identifier, (long) 3, "Mock contents", MetaData.emptyInstance());
    when(mockEventStore.readEvents("test", identifier))
        .thenReturn(
            new SimpleDomainEventStream(
                new GenericDomainEventMessage<String>(
                    identifier, (long) 1, "Mock contents", MetaData.emptyInstance()),
                event2,
                event3));

    try {
      testSubject.load(identifier, 1L);
      fail("Expected ConflictingAggregateVersionException");
    } catch (ConflictingAggregateVersionException e) {
      assertEquals(identifier, e.getAggregateIdentifier());
      assertEquals(1L, e.getExpectedVersion());
      assertEquals(3L, e.getActualVersion());
    }
  }
  @Test
  public void testConstructor() {
    SerializedEventMessage<Object> message1 =
        new SerializedEventMessage<Object>(
            eventId, timestamp, serializedPayload, serializedMetaData, serializer);

    assertSame(MetaData.emptyInstance(), message1.getMetaData());
    assertEquals(Object.class, message1.getPayloadType());
    assertFalse(message1.isPayloadDeserialized());
    assertEquals(Object.class, message1.getPayload().getClass());
    assertTrue(message1.isPayloadDeserialized());
  }
  @Test
  public void testWithMetaData() {
    Map<String, Object> metaDataMap = Collections.singletonMap("key", (Object) "value");
    MetaData metaData = MetaData.from(metaDataMap);
    when(serializer.deserialize(serializedMetaData)).thenReturn(metaData);
    SerializedEventMessage<Object> message =
        new SerializedEventMessage<Object>(
            eventId, timestamp, serializedPayload, serializedMetaData, serializer);
    EventMessage<Object> message1 = message.withMetaData(MetaData.emptyInstance());
    EventMessage<Object> message2 =
        message.withMetaData(MetaData.from(Collections.singletonMap("key", (Object) "otherValue")));

    assertEquals(0, message1.getMetaData().size());
    assertEquals(1, message2.getMetaData().size());
  }
  @Test
  public void testSaveEventsWithDecorators() {
    SpyEventPreprocessor decorator1 = new SpyEventPreprocessor();
    SpyEventPreprocessor decorator2 = new SpyEventPreprocessor();
    testSubject.setEventStreamDecorators(Arrays.asList(decorator1, decorator2));
    testSubject.setEventStore(
        new EventStore() {
          @Override
          public void appendEvents(String type, DomainEventStream events) {
            while (events.hasNext()) {
              events.next();
            }
          }

          @Override
          public DomainEventStream readEvents(String type, Object identifier) {
            return mockEventStore.readEvents(type, identifier);
          }
        });
    UUID identifier = UUID.randomUUID();
    when(mockEventStore.readEvents("test", identifier))
        .thenReturn(
            new SimpleDomainEventStream(
                new GenericDomainEventMessage<String>(
                    identifier, (long) 3, "Mock contents", MetaData.emptyInstance())));
    TestAggregate aggregate = testSubject.load(identifier);
    aggregate.apply(new StubDomainEvent());
    aggregate.apply(new StubDomainEvent());

    CurrentUnitOfWork.commit();

    InOrder inOrder = Mockito.inOrder(decorator1.lastSpy, decorator2.lastSpy);
    inOrder.verify(decorator1.lastSpy).next();
    inOrder.verify(decorator2.lastSpy).next();

    inOrder.verify(decorator1.lastSpy).next();
    inOrder.verify(decorator2.lastSpy).next();
  }
/** @author Allard Buijze */
public class SerializedEventMessageTest {

  private SerializedObject<String> serializedPayload =
      new SimpleSerializedObject<String>("serialized", String.class, "java.lang.Object", "1");
  private SerializedObject<String> serializedMetaData =
      new SerializedMetaData<String>("serialized", String.class);

  private Object deserializedPayload = new Object();
  private MetaData deserializedMetaData = MetaData.emptyInstance();
  private Serializer serializer = mock(Serializer.class);
  private String eventId = "eventId";
  private DateTime timestamp = new DateTime();

  @Before
  public void setUp() {
    when(serializer.deserialize(serializedMetaData)).thenReturn(deserializedMetaData);
    when(serializer.deserialize(serializedPayload)).thenReturn(deserializedPayload);
    when(serializer.classForType(isA(SerializedType.class))).thenReturn(Object.class);
  }

  @Test
  public void testConstructor() {
    SerializedEventMessage<Object> message1 =
        new SerializedEventMessage<Object>(
            eventId, timestamp, serializedPayload, serializedMetaData, serializer);

    assertSame(MetaData.emptyInstance(), message1.getMetaData());
    assertEquals(Object.class, message1.getPayloadType());
    assertFalse(message1.isPayloadDeserialized());
    assertEquals(Object.class, message1.getPayload().getClass());
    assertTrue(message1.isPayloadDeserialized());
  }

  @Test
  public void testWithMetaData() {
    Map<String, Object> metaDataMap = Collections.singletonMap("key", (Object) "value");
    MetaData metaData = MetaData.from(metaDataMap);
    when(serializer.deserialize(serializedMetaData)).thenReturn(metaData);
    SerializedEventMessage<Object> message =
        new SerializedEventMessage<Object>(
            eventId, timestamp, serializedPayload, serializedMetaData, serializer);
    EventMessage<Object> message1 = message.withMetaData(MetaData.emptyInstance());
    EventMessage<Object> message2 =
        message.withMetaData(MetaData.from(Collections.singletonMap("key", (Object) "otherValue")));

    assertEquals(0, message1.getMetaData().size());
    assertEquals(1, message2.getMetaData().size());
  }

  @Test
  public void testAndMetaData() {
    Map<String, Object> metaDataMap = Collections.singletonMap("key", (Object) "value");
    MetaData metaData = MetaData.from(metaDataMap);
    when(serializer.deserialize(serializedMetaData)).thenReturn(metaData);
    EventMessage<Object> message =
        new SerializedEventMessage<Object>(
            eventId, timestamp, serializedPayload, serializedMetaData, serializer);
    EventMessage<Object> message1 = message.andMetaData(MetaData.emptyInstance());
    EventMessage<Object> message2 =
        message.andMetaData(MetaData.from(Collections.singletonMap("key", (Object) "otherValue")));

    assertEquals(1, message1.getMetaData().size());
    assertEquals("value", message1.getMetaData().get("key"));
    assertEquals(1, message2.getMetaData().size());
    assertEquals("otherValue", message2.getMetaData().get("key"));
  }
}
 /**
  * Initialize a new AggregateSnapshot for the given <code>aggregate</code>. Note that the
  * aggregate may not contain uncommitted modifications.
  *
  * @param aggregate The aggregate containing the state to capture in the snapshot
  * @throws IllegalArgumentException if the aggregate contains uncommitted modifications
  */
 public AggregateSnapshot(T aggregate) {
   this(aggregate, MetaData.emptyInstance());
 }
 /**
  * Apply the provided event. Applying events means they are added to the uncommitted event queue
  * and forwarded to the {@link #handle(org.axonframework.domain.DomainEventMessage)} event handler
  * method} for processing.
  *
  * <p>The event is applied on all entities part of this aggregate.
  *
  * @param eventPayload The payload of the event to apply
  */
 protected void apply(Object eventPayload) {
   apply(eventPayload, MetaData.emptyInstance());
 }