Package org.axonframework.eventhandling.async

Source Code of org.axonframework.eventhandling.async.EventProcessorTest$MockEventListener

/*
* Copyright (c) 2010-2012. Axon Framework
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*     http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.axonframework.eventhandling.async;

import org.axonframework.domain.EventMessage;
import org.axonframework.domain.GenericEventMessage;
import org.axonframework.domain.StubDomainEvent;
import org.axonframework.eventhandling.MultiplexingEventProcessingMonitor;
import org.axonframework.eventhandling.EventListener;
import org.axonframework.eventhandling.EventProcessingMonitor;
import org.axonframework.testutils.MockException;
import org.axonframework.unitofwork.DefaultUnitOfWorkFactory;
import org.axonframework.unitofwork.TransactionManager;
import org.junit.*;
import org.mockito.*;

import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

import static org.junit.Assert.*;
import static org.mockito.AdditionalMatchers.*;
import static org.mockito.Mockito.*;

/**
* @author Allard Buijze
*/
@SuppressWarnings("unchecked")
public class EventProcessorTest {

    private EventProcessor testSubject;
    private TransactionManager mockTransactionManager;
    private EventProcessingMonitor eventProcessingMonitor;
    private MultiplexingEventProcessingMonitor multiplexingEventProcessingMonitor;

    @Before
    public void setUp() throws Exception {
        mockTransactionManager = mock(TransactionManager.class);
        when(mockTransactionManager.startTransaction()).thenReturn(new Object());
        eventProcessingMonitor = mock(EventProcessingMonitor.class);
        multiplexingEventProcessingMonitor = new MultiplexingEventProcessingMonitor(eventProcessingMonitor);
    }

    @Test
    public void testEventProcessingSchedule_EventRetried() {
        MockEventListener listener = executeEventProcessing(RetryPolicy.retryAfter(500, TimeUnit.MILLISECONDS));

        verify(mockTransactionManager, times(4)).startTransaction();
        verify(mockTransactionManager, times(3)).commitTransaction(any());
        verify(mockTransactionManager, times(1)).rollbackTransaction(any());
        assertEquals(4, listener.handledEvents.size());
    }

    @Test
    public void testEventProcessingSchedule_FailedEventIgnored() {
        MockEventListener listener = executeEventProcessing(RetryPolicy.proceed());

        // each event is handled twice, since we retry the entire batch
        assertEquals(3, listener.handledEvents.size());
        verify(mockTransactionManager, times(3)).startTransaction();
        verify(mockTransactionManager, times(3)).commitTransaction(any());
    }

    @Test
    public void testEventProcessingDelayed_ScheduledExecutorService() {
        EventMessage<? extends StubDomainEvent> event1 = new GenericEventMessage<StubDomainEvent>(new StubDomainEvent());
        EventMessage<? extends StubDomainEvent> event2 = new GenericEventMessage<StubDomainEvent>(new StubDomainEvent());
        final EventListener listener = mock(EventListener.class);
        ScheduledExecutorService mockExecutorService = mock(ScheduledExecutorService.class);
        testSubject = new EventProcessor(mockExecutorService, new NullShutdownCallback(),
                                         new DefaultErrorHandler(RetryPolicy.retryAfter(500, TimeUnit.MILLISECONDS)),
                                         new DefaultUnitOfWorkFactory(mockTransactionManager),
                                         Collections.singleton(listener), multiplexingEventProcessingMonitor);

        doThrow(new MockException()).doNothing().when(listener).handle(event1);

        testSubject.scheduleEvent(event1);
        testSubject.scheduleEvent(event2);
        testSubject.run();
        verify(mockExecutorService).schedule(eq(testSubject), gt(400L), eq(TimeUnit.MILLISECONDS));
        // since the scheduler is a mock, we simulate the execution:
        testSubject.run();
        InOrder inOrder = inOrder(listener, mockTransactionManager);
        inOrder.verify(mockTransactionManager).startTransaction();
        inOrder.verify(listener).handle(event1);
        inOrder.verify(mockTransactionManager).rollbackTransaction(any());
        inOrder.verify(mockTransactionManager).startTransaction();
        inOrder.verify(listener).handle(event1);
        inOrder.verify(mockTransactionManager).commitTransaction(any());
        inOrder.verify(mockTransactionManager).startTransaction();
        inOrder.verify(listener).handle(event2);
        inOrder.verify(mockTransactionManager).commitTransaction(any());
    }

    @Test
    public void testEventProcessingDelayed_ExecutorDoesNotSupportScheduling() {
        EventMessage<? extends StubDomainEvent> event1 = new GenericEventMessage<StubDomainEvent>(new StubDomainEvent());
        EventMessage<? extends StubDomainEvent> event2 = new GenericEventMessage<StubDomainEvent>(new StubDomainEvent());
        final EventListener listener = mock(EventListener.class);
        ExecutorService mockExecutorService = mock(ExecutorService.class);
        testSubject = new EventProcessor(mockExecutorService, new NullShutdownCallback(),
                                         new DefaultErrorHandler(RetryPolicy.retryAfter(500, TimeUnit.MILLISECONDS)),
                                         new DefaultUnitOfWorkFactory(mockTransactionManager),
                                         Collections.singleton(listener), multiplexingEventProcessingMonitor);
        doThrow(new MockException()).doNothing().when(listener).handle(event1);
        testSubject.scheduleEvent(event1);
        testSubject.scheduleEvent(event2);
        long t1 = System.currentTimeMillis();
        testSubject.run();
        // we simulate the immediate scheduling of the yielded task by executing run again
        testSubject.run();
        long t2 = System.currentTimeMillis();
        // we allow some slack, because thread scheduling doesn't give us much guarantees about timing
        long waitTime = t2 - t1;
        assertTrue("Wait time was too short: " + waitTime, waitTime > 480);

        InOrder inOrder = inOrder(listener, mockTransactionManager);
        inOrder.verify(mockTransactionManager).startTransaction();
        inOrder.verify(listener).handle(event1);
        inOrder.verify(mockTransactionManager).rollbackTransaction(any());
        inOrder.verify(mockTransactionManager).startTransaction();
        inOrder.verify(listener).handle(event1);
        inOrder.verify(mockTransactionManager).commitTransaction(any());
        inOrder.verify(mockTransactionManager).startTransaction();
        inOrder.verify(listener).handle(event2);
        inOrder.verify(mockTransactionManager).commitTransaction(any());
    }

    /**
     * This test verifies issue #15 (http://code.google.com/p/axonframework/issues/detail?id=15)
     */
    @Test
    public void testEventProcessingRetried_TransactionStartupFails() {
        EventMessage<? extends StubDomainEvent> event1 = new GenericEventMessage<StubDomainEvent>(new StubDomainEvent());
        EventMessage<? extends StubDomainEvent> event2 = new GenericEventMessage<StubDomainEvent>(new StubDomainEvent());
        final EventListener listener = mock(EventListener.class);
        ExecutorService mockExecutorService = mock(ExecutorService.class);
        testSubject = new EventProcessor(mockExecutorService, new NullShutdownCallback(),
                                         new DefaultErrorHandler(RetryPolicy.retryAfter(500, TimeUnit.MILLISECONDS)),
                                         new DefaultUnitOfWorkFactory(mockTransactionManager),
                                         Collections.singleton(listener), multiplexingEventProcessingMonitor);

        doThrow(new MockException()).doReturn(new Object()).when(mockTransactionManager).startTransaction();
        testSubject.scheduleEvent(event1);
        testSubject.scheduleEvent(event2);
        testSubject.run();
        verify(mockExecutorService, times(2)).execute(eq(testSubject));
        verify(listener, never()).handle(event1);
        // since the scheduler is a mock, we simulate the execution:
        testSubject.run();
        InOrder inOrder = inOrder(listener, mockTransactionManager);
        inOrder.verify(mockTransactionManager, times(2)).startTransaction();
        // make sure the first event is not skipped by verifying that event1 is handled
        inOrder.verify(listener).handle(event1);
        inOrder.verify(mockTransactionManager).commitTransaction(any());
        inOrder.verify(mockTransactionManager).startTransaction();
        inOrder.verify(listener).handle(event2);
        inOrder.verify(mockTransactionManager).commitTransaction(any());
    }

    private MockEventListener executeEventProcessing(RetryPolicy policy) {
        ExecutorService mockExecutorService = mock(ExecutorService.class);
        final MockEventListener listener = new MockEventListener();
        testSubject = new EventProcessor(mockExecutorService, new NullShutdownCallback(),
                                         new DefaultErrorHandler(policy),
                                         new DefaultUnitOfWorkFactory(mockTransactionManager),
                                         Collections.<EventListener>singleton(listener),
                                         multiplexingEventProcessingMonitor);
        doNothing().doThrow(new RejectedExecutionException()).when(mockExecutorService).execute(isA(Runnable.class));
        testSubject.scheduleEvent(new GenericEventMessage<StubDomainEvent>(new StubDomainEvent()));
        listener.failOnEvent = 2;
        testSubject.scheduleEvent(new GenericEventMessage<StubDomainEvent>(new StubDomainEvent()));
        testSubject.scheduleEvent(new GenericEventMessage<StubDomainEvent>(new StubDomainEvent()));

        testSubject.run();
        return listener;
    }

    private class MockEventListener implements EventListener {

        private int failOnEvent;
        private List<EventMessage<?>> handledEvents = new LinkedList<EventMessage<?>>();

        @Override
        public void handle(EventMessage event) {
            handledEvents.add(event);
            if (--failOnEvent == 0) {
                throw new MockException();
            }
        }
    }

    private static class NullShutdownCallback implements EventProcessor.ShutdownCallback {

        @Override
        public void afterShutdown(EventProcessor scheduler) {
        }
    }
}
TOP

Related Classes of org.axonframework.eventhandling.async.EventProcessorTest$MockEventListener

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.