package de.otto.edison.jobs.eventbus;
import de.otto.edison.jobs.definition.JobDefinition;
import de.otto.edison.jobs.domain.JobMessage;
import de.otto.edison.jobs.eventbus.events.MessageEvent;
import de.otto.edison.jobs.eventbus.events.StateChangeEvent;
import de.otto.edison.jobs.service.JobRunnable;
import de.otto.edison.jobs.service.JobService;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mock;
import java.time.Instant;
import java.time.OffsetDateTime;
import java.time.ZoneId;
import java.util.Optional;
import static de.otto.edison.jobs.domain.Level.INFO;
import static de.otto.edison.jobs.eventbus.events.MessageEvent.newMessageEvent;
import static de.otto.edison.jobs.eventbus.events.StateChangeEvent.State.*;
import static de.otto.edison.jobs.eventbus.events.StateChangeEvent.newStateChangeEvent;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import static org.mockito.MockitoAnnotations.initMocks;
public class PersistenceJobEventListenerTest {
public static final String JOB_ID = "some/job/id";
public static final String JOB_TYPE = "jobType";
@Mock
private JobService jobServiceMock;
@Mock
private JobRunnable jobRunnableMock;
private PersistenceJobEventListener subject;
@Before
public void setUp() throws Exception {
initMocks(this);
when(jobRunnableMock.getJobDefinition()).thenReturn(mock(JobDefinition.class));
subject = new PersistenceJobEventListener(jobServiceMock);
}
@Test
public void shouldPersistStillAliveEvent() throws Exception {
subject.consumeStateChange(stateChangedEvent(KEEP_ALIVE));
verify(jobServiceMock).keepAlive(JOB_ID);
}
@Test
public void shouldPersistRestartEvent() throws Exception {
subject.consumeStateChange(stateChangedEvent(RESTART));
verify(jobServiceMock).markRestarted(JOB_ID);
}
@Test
public void shouldPersistDeadEvent() throws Exception {
JobDefinition mockDefinition = mock(JobDefinition.class);
when(mockDefinition.jobType()).thenReturn(JOB_TYPE);
when(jobRunnableMock.getJobDefinition()).thenReturn(mockDefinition);
subject.consumeStateChange(stateChangedEvent(DEAD));
verify(jobServiceMock).killJob(JOB_ID, JOB_TYPE);
}
@Test
public void shouldPersistStopEvent() throws Exception {
subject.consumeStateChange(stateChangedEvent(STOP));
verify(jobServiceMock).stopJob(JOB_ID);
}
@Test
public void shouldPersistSkippedEvent() throws Exception {
subject.consumeStateChange(stateChangedEvent(SKIPPED));
verify(jobServiceMock).markSkipped(JOB_ID);
}
@Test
public void shouldPersistMessage() throws Exception {
MessageEvent messageEvent = newMessageEvent(jobRunnableMock, JOB_ID, INFO, "some message", Optional.empty());
OffsetDateTime timestamp = OffsetDateTime.ofInstant(Instant.ofEpochMilli(messageEvent.getTimestamp()), ZoneId.systemDefault());
subject.consumeMessage(messageEvent);
verify(jobServiceMock).appendMessage(JOB_ID, JobMessage.jobMessage(INFO, "some message", timestamp));
}
@Test
public void shouldNotThrowIfSomethingFailsInDatabase() {
MessageEvent messageEvent = newMessageEvent(jobRunnableMock, JOB_ID, INFO, "some message", Optional.empty());
OffsetDateTime timestamp = OffsetDateTime.ofInstant(Instant.ofEpochMilli(messageEvent.getTimestamp()), ZoneId.systemDefault());
final JobMessage expectedJobMessage = JobMessage.jobMessage(INFO, "some message", timestamp);
doThrow(new RuntimeException("Miserable failure")).when(jobServiceMock).appendMessage(JOB_ID, expectedJobMessage);
subject.consumeMessage(messageEvent);
verify(jobServiceMock).appendMessage(JOB_ID, expectedJobMessage);
}
@Test
public void shouldNotThrowIfStateChangeFailsInDatabase() throws Exception {
doThrow(new RuntimeException("Unexpected disturbance in the force")).when(jobServiceMock).stopJob(JOB_ID);
subject.consumeStateChange(stateChangedEvent(STOP));
verify(jobServiceMock).stopJob(JOB_ID);
}
private StateChangeEvent stateChangedEvent(StateChangeEvent.State stop) {
return newStateChangeEvent(jobRunnableMock, JOB_ID, stop);
}
}