/*
* 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.scheduling.quartz;
import org.axonframework.common.transaction.Transaction;
import org.axonframework.common.transaction.TransactionManager;
import org.axonframework.eventhandling.EventBus;
import org.axonframework.eventhandling.EventMessage;
import org.axonframework.eventhandling.GenericEventMessage;
import org.axonframework.eventhandling.saga.Saga;
import org.axonframework.eventhandling.scheduling.ScheduleToken;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.mockito.InOrder;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.SchedulerFactory;
import org.quartz.impl.matchers.GroupMatcher;
import java.time.Duration;
import java.util.UUID;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.*;
/**
* @author Allard Buijze
*/
public class QuartzEventSchedulerTest {
private static final String GROUP_ID = "TestGroup";
private QuartzEventScheduler testSubject;
private EventBus eventBus;
private Scheduler scheduler;
@Before
public void setUp() throws SchedulerException {
eventBus = mock(EventBus.class);
SchedulerFactory schedFact = new org.quartz.impl.StdSchedulerFactory();
testSubject = new QuartzEventScheduler();
scheduler = schedFact.getScheduler();
scheduler.getContext().put(EventBus.class.getName(), eventBus);
scheduler.start();
testSubject.setScheduler(scheduler);
testSubject.setEventBus(eventBus);
testSubject.setGroupIdentifier(GROUP_ID);
testSubject.initialize();
}
@After
public void tearDown() throws SchedulerException {
if (scheduler != null) {
scheduler.shutdown(true);
}
}
@Test
public void testScheduleJob() throws InterruptedException {
final CountDownLatch latch = new CountDownLatch(1);
doAnswer(invocation -> {
latch.countDown();
return null;
}).when(eventBus).publish(isA(EventMessage.class));
Saga mockSaga = mock(Saga.class);
when(mockSaga.getSagaIdentifier()).thenReturn(UUID.randomUUID().toString());
ScheduleToken token = testSubject.schedule(Duration.ofMillis(30), new StubEvent());
assertTrue(token.toString().contains("Quartz"));
assertTrue(token.toString().contains(GROUP_ID));
latch.await(1, TimeUnit.SECONDS);
verify(eventBus).publish(isA(EventMessage.class));
}
@SuppressWarnings("unchecked")
@Test
public void testScheduleJob_TransactionalUnitOfWork() throws InterruptedException, SchedulerException {
Transaction mockTransaction = mock(Transaction.class);
final TransactionManager transactionManager = mock(TransactionManager.class);
when(transactionManager.startTransaction()).thenReturn(mockTransaction);
testSubject.setTransactionManager(transactionManager);
testSubject.initialize();
final CountDownLatch latch = new CountDownLatch(1);
doAnswer(invocation -> {
latch.countDown();
return null;
}).when(eventBus).publish(isA(EventMessage.class));
Saga mockSaga = mock(Saga.class);
when(mockSaga.getSagaIdentifier()).thenReturn(UUID.randomUUID().toString());
ScheduleToken token = testSubject.schedule(Duration.ofMillis(30), new StubEvent());
assertTrue(token.toString().contains("Quartz"));
assertTrue(token.toString().contains(GROUP_ID));
latch.await(1, TimeUnit.SECONDS);
InOrder inOrder = inOrder(transactionManager, eventBus, mockTransaction);
inOrder.verify(transactionManager).startTransaction();
inOrder.verify(eventBus).publish(isA(EventMessage.class));
inOrder.verify(mockTransaction).commit();
}
@Test
public void testCancelJob() throws SchedulerException, InterruptedException {
Saga mockSaga = mock(Saga.class);
when(mockSaga.getSagaIdentifier()).thenReturn(UUID.randomUUID().toString());
ScheduleToken token = testSubject.schedule(Duration.ofMillis(1000), new StubEvent());
assertEquals(1, scheduler.getJobKeys(GroupMatcher.groupEquals(GROUP_ID)).size());
testSubject.cancelSchedule(token);
assertEquals(0, scheduler.getJobKeys(GroupMatcher.groupEquals(GROUP_ID)).size());
scheduler.shutdown(true);
verify(eventBus, never()).publish(isA(EventMessage.class));
}
private EventMessage newStubEvent() {
return new GenericEventMessage<>(new StubEvent());
}
private class StubEvent {
}
}