You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
152 lines
6.0 KiB
152 lines
6.0 KiB
package com.autovoucher.job;
|
|
|
|
import com.autovoucher.config.AppProperties;
|
|
import com.autovoucher.domain.PushTask;
|
|
import com.autovoucher.repository.PushTaskRepository;
|
|
import com.autovoucher.service.PushService;
|
|
import org.junit.jupiter.api.Test;
|
|
import org.mockito.InOrder;
|
|
|
|
import java.time.LocalDateTime;
|
|
import java.util.List;
|
|
|
|
import static org.assertj.core.api.Assertions.assertThat;
|
|
import static org.mockito.ArgumentMatchers.any;
|
|
import static org.mockito.ArgumentMatchers.eq;
|
|
import static org.mockito.Mockito.doThrow;
|
|
import static org.mockito.Mockito.inOrder;
|
|
import static org.mockito.Mockito.mock;
|
|
import static org.mockito.Mockito.never;
|
|
import static org.mockito.Mockito.times;
|
|
import static org.mockito.Mockito.verify;
|
|
import static org.mockito.Mockito.verifyNoInteractions;
|
|
import static org.mockito.Mockito.when;
|
|
|
|
class NccPushRunnerTest {
|
|
|
|
private final AppProperties properties = new AppProperties();
|
|
private final PushTaskRepository pushTaskRepository = mock(PushTaskRepository.class);
|
|
private final PushService pushService = mock(PushService.class);
|
|
private final NccPushRunner runner =
|
|
new NccPushRunner(properties, pushTaskRepository, pushService);
|
|
|
|
@Test
|
|
void disabledPushSkipsAllRepositoryWork() {
|
|
properties.getPush().setEnabled(false);
|
|
|
|
NccPushRunner.Result result = runner.runDue(1L, 20);
|
|
|
|
assertThat(result.enabled()).isFalse();
|
|
assertThat(result.failedTaskIds()).isEmpty();
|
|
verifyNoInteractions(pushTaskRepository, pushService);
|
|
}
|
|
|
|
@Test
|
|
void reconcilesUnknownTasksBeforePushingPendingOnes() {
|
|
PushTask unknown = task(1L);
|
|
PushTask due = task(2L);
|
|
when(pushTaskRepository.findDueTasks(eq(1L), eq("NCC"), eq(List.of("UNKNOWN")), any()))
|
|
.thenReturn(List.of(unknown));
|
|
when(pushTaskRepository.findDueTasks(eq(1L), eq("NCC"),
|
|
eq(List.of("PENDING", "RETRY_WAIT")), any()))
|
|
.thenReturn(List.of(due));
|
|
|
|
NccPushRunner.Result result = runner.runDue(1L, 20);
|
|
|
|
assertThat(result.enabled()).isTrue();
|
|
assertThat(result.reconciled()).isEqualTo(1);
|
|
assertThat(result.pushed()).isEqualTo(1);
|
|
assertThat(result.failed()).isZero();
|
|
assertThat(result.partialFailure()).isFalse();
|
|
assertThat(result.allAttemptsFailed()).isFalse();
|
|
|
|
InOrder order = inOrder(pushService);
|
|
order.verify(pushService).reconcile(1L);
|
|
order.verify(pushService).push(2L, null);
|
|
}
|
|
|
|
@Test
|
|
void oneFailingTaskDoesNotStopTheRest() {
|
|
PushTask badReconcile = task(1L);
|
|
PushTask badPush = task(2L);
|
|
PushTask goodPush = task(3L);
|
|
when(pushTaskRepository.findDueTasks(eq(1L), eq("NCC"), eq(List.of("UNKNOWN")), any()))
|
|
.thenReturn(List.of(badReconcile));
|
|
when(pushTaskRepository.findDueTasks(eq(1L), eq("NCC"),
|
|
eq(List.of("PENDING", "RETRY_WAIT")), any()))
|
|
.thenReturn(List.of(badPush, goodPush));
|
|
when(pushService.reconcile(1L)).thenThrow(new IllegalStateException("reconcile boom"));
|
|
doThrow(new IllegalStateException("push boom")).when(pushService).push(2L, null);
|
|
|
|
NccPushRunner.Result result = runner.runDue(1L, 20);
|
|
|
|
assertThat(result.reconciled()).isZero();
|
|
assertThat(result.pushed()).isEqualTo(1);
|
|
assertThat(result.failed()).isEqualTo(2);
|
|
assertThat(result.failedTaskIds()).containsExactly(1L, 2L);
|
|
assertThat(result.partialFailure()).isTrue();
|
|
assertThat(result.allAttemptsFailed()).isFalse();
|
|
verify(pushService).push(3L, null);
|
|
}
|
|
|
|
@Test
|
|
void allAttemptsFailingIsReportedAsTotalFailure() {
|
|
when(pushTaskRepository.findDueTasks(eq(1L), eq("NCC"), eq(List.of("UNKNOWN")), any()))
|
|
.thenReturn(List.of());
|
|
when(pushTaskRepository.findDueTasks(eq(1L), eq("NCC"),
|
|
eq(List.of("PENDING", "RETRY_WAIT")), any()))
|
|
.thenReturn(List.of(task(2L)));
|
|
doThrow(new IllegalStateException("push boom")).when(pushService).push(2L, null);
|
|
|
|
NccPushRunner.Result result = runner.runDue(1L, 20);
|
|
|
|
assertThat(result.failed()).isEqualTo(1);
|
|
assertThat(result.allAttemptsFailed()).isTrue();
|
|
assertThat(result.partialFailure()).isFalse();
|
|
}
|
|
|
|
@Test
|
|
void batchSizeLimitsBothReconcileAndPushRounds() {
|
|
when(pushTaskRepository.findDueTasks(eq(1L), eq("NCC"), eq(List.of("UNKNOWN")), any()))
|
|
.thenReturn(List.of(task(1L), task(2L), task(3L)));
|
|
when(pushTaskRepository.findDueTasks(eq(1L), eq("NCC"),
|
|
eq(List.of("PENDING", "RETRY_WAIT")), any()))
|
|
.thenReturn(List.of(task(4L), task(5L), task(6L)));
|
|
|
|
NccPushRunner.Result result = runner.runDue(1L, 2);
|
|
|
|
assertThat(result.reconciled()).isEqualTo(2);
|
|
assertThat(result.pushed()).isEqualTo(2);
|
|
verify(pushService).reconcile(1L);
|
|
verify(pushService).reconcile(2L);
|
|
verify(pushService, never()).reconcile(3L);
|
|
verify(pushService).push(4L, null);
|
|
verify(pushService).push(5L, null);
|
|
verify(pushService, never()).push(6L, null);
|
|
}
|
|
|
|
@Test
|
|
void nonPositiveBatchSizeStillProcessesOneTask() {
|
|
when(pushTaskRepository.findDueTasks(eq(1L), eq("NCC"), eq(List.of("UNKNOWN")), any()))
|
|
.thenReturn(List.of());
|
|
when(pushTaskRepository.findDueTasks(eq(1L), eq("NCC"),
|
|
eq(List.of("PENDING", "RETRY_WAIT")), any()))
|
|
.thenReturn(List.of(task(4L), task(5L)));
|
|
|
|
NccPushRunner.Result result = runner.runDue(1L, 0);
|
|
|
|
assertThat(result.pushed()).isEqualTo(1);
|
|
verify(pushService, times(1)).push(4L, null);
|
|
verify(pushService, never()).push(5L, null);
|
|
}
|
|
|
|
private PushTask task(Long id) {
|
|
PushTask task = new PushTask();
|
|
task.setId(id);
|
|
task.setTenantId(1L);
|
|
task.setTargetSystem("NCC");
|
|
task.setStatus("PENDING");
|
|
task.setNextRetryAt(LocalDateTime.now().minusMinutes(1));
|
|
return task;
|
|
}
|
|
}
|
|
|