990 lines
35 KiB
C#
990 lines
35 KiB
C#
using LCU.Api.Internal.Dispatcher.Configurations;
|
|
using LCU.Api.Internal.Dispatcher.Services;
|
|
using LCU.Api.Internal.DispatcherLib.Repositories;
|
|
using LCU.Api.Internal.DispatcherSharedLib.Utilities;
|
|
using LCU.Library.Internal.DispatcherModels.Enums;
|
|
using LCU.Library.Internal.DispatcherModels.Models.Requests;
|
|
using LCU.Library.Internal.DispatcherModels.Models.Results;
|
|
using NCrontab;
|
|
using System.Collections.Generic;
|
|
|
|
namespace LCU.Api.Internal.DispatcherTests.ServiceTests;
|
|
|
|
public class JobServiceTest
|
|
{
|
|
private readonly JobService _jobService;
|
|
private readonly Mock<IUnitOfWork> _mockUnitOfWork;
|
|
private readonly Mock<IJobRepository> _mockJobRepository;
|
|
private readonly Mock<IWorkItemService> _mockWorkItemService;
|
|
private readonly Mock<IWorkItemExecutionService> _mockWorkItemExecutionService;
|
|
private readonly ApiConfiguration _apiConfiguration;
|
|
|
|
public JobServiceTest()
|
|
{
|
|
_mockJobRepository = new Mock<IJobRepository>();
|
|
_mockWorkItemService = new Mock<IWorkItemService>();
|
|
_mockWorkItemExecutionService = new Mock<IWorkItemExecutionService>();
|
|
_mockUnitOfWork = new Mock<IUnitOfWork>();
|
|
|
|
_apiConfiguration = new ApiConfiguration()
|
|
{
|
|
NumberOfWorkItemExecutions = 10,
|
|
NumberOfExecutionMessages = 20,
|
|
ProcessingLimitInMinutes = 30,
|
|
JobStatusesToMonitorByTimeLimit = new List<JobStatus>() { JobStatus.Processing }
|
|
};
|
|
|
|
|
|
_jobService = new JobService(_mockUnitOfWork.Object,
|
|
_mockJobRepository.Object,
|
|
_mockWorkItemService.Object,
|
|
_mockWorkItemExecutionService.Object,
|
|
_apiConfiguration);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task GetListAsync_Success()
|
|
{
|
|
// Arrange
|
|
_mockJobRepository.Setup(repo => repo.ListAsync(10, 20)).ReturnsAsync(new List<Job>()
|
|
{
|
|
new Job(),
|
|
new Job()
|
|
});
|
|
|
|
// Act
|
|
var result = await _jobService.GetAsync();
|
|
|
|
// Assert
|
|
Assert.NotNull(result);
|
|
Assert.Equal(2, result.Count());
|
|
}
|
|
|
|
[Fact]
|
|
public async Task GetByIdAsync_Success()
|
|
{
|
|
// Arrange
|
|
_mockJobRepository.Setup(repo => repo.FindByIdAsync(It.IsAny<int>(), 10, 20)).ReturnsAsync(new Job());
|
|
|
|
// Act
|
|
var result = await _jobService.GetByIdAsync(1);
|
|
|
|
// Assert
|
|
Assert.NotNull(result);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task SaveAsync_Success()
|
|
{
|
|
// Arrange
|
|
_mockJobRepository.Setup(repo => repo.AddAsync(It.IsAny<Job>())).ReturnsAsync(new Job());
|
|
|
|
// Act
|
|
var result = await _jobService.SaveAsync(new Job());
|
|
|
|
// Assert
|
|
Assert.NotNull(result);
|
|
_mockJobRepository.Verify(x => x.AddAsync(It.IsAny<Job>()), Times.Once);
|
|
_mockUnitOfWork.Verify(x => x.CompleteAsync(), Times.Once);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task UpdateAsync_Success()
|
|
{
|
|
// Arrange
|
|
var jobToUpdate = new Job()
|
|
{
|
|
JobId = 1,
|
|
RequestingApplication = "App"
|
|
};
|
|
|
|
_mockJobRepository.Setup(repo => repo.Update(It.IsAny<Job>())).ReturnsAsync(jobToUpdate).Verifiable();
|
|
|
|
// Act
|
|
var result = await _jobService.UpdateAsync(jobToUpdate);
|
|
|
|
// Assert
|
|
Assert.NotNull(result);
|
|
Assert.Equal(jobToUpdate.JobId, result.JobId);
|
|
Assert.Equal(jobToUpdate.RequestingApplication, result.RequestingApplication);
|
|
_mockJobRepository.Verify(x => x.FindByIdAsync(It.IsAny<int>(), 10, 20), Times.Never);
|
|
_mockJobRepository.Verify(x => x.Update(It.IsAny<Job>()), Times.Once);
|
|
_mockUnitOfWork.Verify(x => x.CompleteAsync(), Times.Once);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task CompleteJobAndWorkItem_Success_NoReschedule()
|
|
{
|
|
// Arrange
|
|
var jobToUpdate = new Job()
|
|
{
|
|
JobId = 1,
|
|
RequestingApplication = "App",
|
|
NextRunTime = Convert.ToDateTime("1/1/2022")
|
|
};
|
|
|
|
_mockJobRepository.Setup(repo => repo.FindByIdExcludingWorkItemsAsync(1)).ReturnsAsync(jobToUpdate);
|
|
var updatedJob = new Job()
|
|
{
|
|
JobId = 1,
|
|
RequestingApplication = "App",
|
|
NextRunTime = null
|
|
};
|
|
_mockJobRepository.Setup(repo => repo.Update(It.IsAny<Job>())).ReturnsAsync(updatedJob).Verifiable();
|
|
|
|
var updatedWorkitemExecution = new WorkItemExecution()
|
|
{
|
|
WorkItemExecutionId = 1,
|
|
Status = StatusType.Completed
|
|
};
|
|
_mockWorkItemExecutionService.Setup(repo => repo.UpdateCompleteWorkItemExecutionWithoutSave(It.IsAny<WorkItemExecution>(), StatusType.Completed)).ReturnsAsync(updatedWorkitemExecution);
|
|
|
|
_mockUnitOfWork.Setup(uow => uow.CompleteAsync()).Returns(Task.CompletedTask);
|
|
|
|
// Act
|
|
await _jobService.CompleteJobAndWorkItem(jobToUpdate, new WorkItemExecution(100), StatusType.Completed);
|
|
|
|
// Assert
|
|
_mockJobRepository.Verify(x => x.FindByIdExcludingWorkItemsAsync(1), Times.Never);
|
|
_mockJobRepository.Verify(x => x.Update(It.IsAny<Job>()), Times.Once);
|
|
_mockWorkItemExecutionService.Verify(x => x.UpdateCompleteWorkItemExecutionWithoutSave(It.IsAny<WorkItemExecution>(), It.IsAny<StatusType>()), Times.Once);
|
|
_mockUnitOfWork.Verify(x => x.CompleteAsync(), Times.Once);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task CompleteJobAndWorkItem_Success_Reschedule()
|
|
{
|
|
// Arrange
|
|
var jobToUpdate = new Job()
|
|
{
|
|
JobId = 1,
|
|
RequestingApplication = "App",
|
|
NextRunTime = Convert.ToDateTime("1/1/2022"),
|
|
CronSchedule = "5 * * * *"
|
|
};
|
|
|
|
_mockJobRepository.Setup(repo => repo.FindByIdExcludingWorkItemsAsync(1)).ReturnsAsync(jobToUpdate);
|
|
var updatedJob = new Job()
|
|
{
|
|
JobId = 1,
|
|
RequestingApplication = "App",
|
|
NextRunTime = DateTime.Now.AddSeconds(5)
|
|
};
|
|
_mockJobRepository.Setup(repo => repo.Update(It.IsAny<Job>())).ReturnsAsync(updatedJob).Verifiable();
|
|
|
|
var updatedWorkitemExecution = new WorkItemExecution()
|
|
{
|
|
WorkItemExecutionId = 1,
|
|
Status = StatusType.Completed
|
|
};
|
|
_mockWorkItemExecutionService.Setup(repo => repo.UpdateCompleteWorkItemExecutionWithoutSave(It.IsAny<WorkItemExecution>(), It.IsAny<StatusType>())).ReturnsAsync(updatedWorkitemExecution);
|
|
|
|
_mockUnitOfWork.Setup(uow => uow.CompleteAsync()).Returns(Task.CompletedTask);
|
|
|
|
// Act
|
|
await _jobService.CompleteJobAndWorkItem(jobToUpdate, new WorkItemExecution(100), StatusType.Completed);
|
|
|
|
// Assert
|
|
_mockJobRepository.Verify(x => x.FindByIdExcludingWorkItemsAsync(1), Times.Never);
|
|
_mockJobRepository.Verify(x => x.Update(It.IsAny<Job>()), Times.Once);
|
|
_mockWorkItemExecutionService.Verify(x => x.UpdateCompleteWorkItemExecutionWithoutSave(It.IsAny<WorkItemExecution>(), It.IsAny<StatusType>()), Times.Once);
|
|
_mockUnitOfWork.Verify(x => x.CompleteAsync(), Times.Once);
|
|
}
|
|
|
|
[Fact]
|
|
public void HolidayHelper_Success_SkipMemorialDayHolidayNextOccurrence()
|
|
{
|
|
// Arrange
|
|
var jobToUpdate = new Job()
|
|
{
|
|
JobId = 1,
|
|
SkipHolidays = true,
|
|
RequestingApplication = "App",
|
|
CronSchedule = "0 0 1-30 5 *"
|
|
};
|
|
|
|
CrontabSchedule schedule = CrontabSchedule.Parse(jobToUpdate.CronSchedule);
|
|
var nextRunTime = schedule.GetNextOccurrence(DateTime.Now);
|
|
|
|
var memorialDay = HolidayHelpers.GetMemorialDay(nextRunTime.Year); //stage next possible holiday date, reset cron
|
|
jobToUpdate.NextRunTime = memorialDay;
|
|
jobToUpdate.CronSchedule = $"0 0 {memorialDay.Day} {memorialDay.Month} *";
|
|
|
|
// Assert
|
|
Assert.NotNull(jobToUpdate);
|
|
Assert.Equal(memorialDay, jobToUpdate.NextRunTime);
|
|
}
|
|
|
|
[Fact]
|
|
public void HolidayHelper_Success_SkipThanksGivingHolidayNextOccurrence()
|
|
{
|
|
// Arrange
|
|
var jobToUpdate = new Job()
|
|
{
|
|
JobId = 1,
|
|
SkipHolidays = true,
|
|
RequestingApplication = "App",
|
|
CronSchedule = "0 0 22-30 11 *"
|
|
};
|
|
|
|
CrontabSchedule schedule = CrontabSchedule.Parse(jobToUpdate.CronSchedule);
|
|
var nextRunTime = schedule.GetNextOccurrence(DateTime.Now);
|
|
|
|
var thanksgivingDay = HolidayHelpers.GetThanksgivingDay(nextRunTime.Year); //stage next possible holiday date, reset cron
|
|
jobToUpdate.NextRunTime = thanksgivingDay;
|
|
jobToUpdate.CronSchedule = $"0 0 {thanksgivingDay.Day} {thanksgivingDay.Month} *";
|
|
|
|
// Assert
|
|
Assert.NotNull(jobToUpdate);
|
|
Assert.Equal(thanksgivingDay, jobToUpdate.NextRunTime);
|
|
}
|
|
|
|
[Fact]
|
|
public void HolidayHelper_Success_SkipIndependenceDayHolidayNextOccurrence()
|
|
{
|
|
// Arrange
|
|
var jobToUpdate = new Job()
|
|
{
|
|
JobId = 1,
|
|
SkipHolidays = true,
|
|
RequestingApplication = "App",
|
|
CronSchedule = "0 0 4-31 7 *"
|
|
};
|
|
|
|
CrontabSchedule schedule = CrontabSchedule.Parse(jobToUpdate.CronSchedule);
|
|
var nextRunTime = schedule.GetNextOccurrence(DateTime.Now);
|
|
|
|
CronHelpers.SetNextScheduledRunTime(ref jobToUpdate);
|
|
var nextRunTimeAfterHoliday = HolidayHelpers.HandleHolidays(nextRunTime);
|
|
|
|
// Assert
|
|
Assert.NotNull(jobToUpdate);
|
|
Assert.Equal(nextRunTimeAfterHoliday, jobToUpdate.NextRunTime);
|
|
}
|
|
|
|
[Fact]
|
|
public void HolidayHelper_Success_SkipLaborDayHolidayNextOccurrence()
|
|
{
|
|
// Arrange
|
|
var jobToUpdate = new Job()
|
|
{
|
|
JobId = 1,
|
|
SkipHolidays = true,
|
|
RequestingApplication = "App",
|
|
CronSchedule = "0 0 1-30 9 *"
|
|
};
|
|
|
|
CrontabSchedule schedule = CrontabSchedule.Parse(jobToUpdate.CronSchedule);
|
|
var nextRunTime = schedule.GetNextOccurrence(DateTime.Now);
|
|
|
|
var laborDay = HolidayHelpers.GetLaborDay(nextRunTime.Year); //stage next possible holiday date, reset cron
|
|
jobToUpdate.NextRunTime = laborDay;
|
|
jobToUpdate.CronSchedule = $"0 0 {laborDay.Day} {laborDay.Month} *";
|
|
var nextRunTimeAfterHoliday = HolidayHelpers.GetLaborDay(nextRunTime.Year);
|
|
|
|
// Assert
|
|
Assert.NotNull(jobToUpdate);
|
|
Assert.Equal(nextRunTimeAfterHoliday, jobToUpdate.NextRunTime);
|
|
}
|
|
|
|
[Fact]
|
|
public void GetJobsProcessingLongerThanTime_Return_OneProcessingJob_LongerThen_30minutes()
|
|
{
|
|
// Arrange
|
|
var jobs = new List<Job>()
|
|
{
|
|
new Job()
|
|
{
|
|
Name = "Test Process Job",
|
|
NextRunTime = DateTime.Now.AddHours(-1),
|
|
WorkItems = new List<WorkItem>() {
|
|
new WorkItem()
|
|
{
|
|
Name = "Test Process WorkItem",
|
|
WorkItemExecutions = new List<WorkItemExecution>(){
|
|
new WorkItemExecution()
|
|
{
|
|
Status = StatusType.Processing,
|
|
StartedTimestamp = DateTime.Now.AddMinutes(-31)
|
|
}
|
|
}
|
|
}
|
|
},
|
|
JobStatus = JobStatus.Processing
|
|
}
|
|
};
|
|
|
|
// Act
|
|
var result = _jobService.GetJobsInStatusLongerThanTimeLimit(jobs, 30);
|
|
|
|
// Assert
|
|
Assert.NotNull(result);
|
|
Assert.Single(result);
|
|
}
|
|
|
|
[Fact]
|
|
public void GetJobsProcessingLongerThanTime_Return_NoneProcessingJob_NotLongerThen_30minutes()
|
|
{
|
|
// Arrange
|
|
var jobs = new List<Job>()
|
|
{
|
|
new Job()
|
|
{
|
|
Name = "Test Failed Job",
|
|
NextRunTime = DateTime.Now.AddHours(-1),
|
|
JobStatus = JobStatus.Failed,
|
|
WorkItems = new List<WorkItem>() {
|
|
new WorkItem()
|
|
{
|
|
Name = "Test Failed WorkItem",
|
|
WorkItemExecutions = new List<WorkItemExecution>(){
|
|
new WorkItemExecution()
|
|
{
|
|
Status = StatusType.Failed,
|
|
StartedTimestamp = DateTime.Now.AddMinutes(-10)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
new Job()
|
|
{
|
|
Name = "Test Process Job",
|
|
NextRunTime = DateTime.Now.AddHours(-1),
|
|
JobStatus = JobStatus.Processing,
|
|
WorkItems = new List<WorkItem>() {
|
|
new WorkItem()
|
|
{
|
|
Name = "Test Process WorkItem",
|
|
WorkItemExecutions = new List<WorkItemExecution>(){
|
|
new WorkItemExecution()
|
|
{
|
|
Status = StatusType.Processing,
|
|
StartedTimestamp = DateTime.Now.AddMinutes(-29)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
// Act
|
|
var result = _jobService.GetJobsInStatusLongerThanTimeLimit(jobs, 30);
|
|
|
|
// Assert
|
|
Assert.NotNull(result);
|
|
Assert.Empty(result);
|
|
}
|
|
|
|
[Fact]
|
|
public void GetJobsProcessingLongerThanTime_Return_NoneProcessingJob_NoneAreProcessing()
|
|
{
|
|
// Arrange
|
|
var jobs = new List<Job>()
|
|
{
|
|
new Job()
|
|
{
|
|
Name = "Test Failed Job",
|
|
NextRunTime = DateTime.Now.AddHours(-1),
|
|
JobStatus = JobStatus.Failed,
|
|
WorkItems = new List<WorkItem>() {
|
|
new WorkItem()
|
|
{
|
|
Name = "Test Failed WorkItem",
|
|
WorkItemExecutions = new List<WorkItemExecution>(){
|
|
new WorkItemExecution()
|
|
{
|
|
Status = StatusType.Failed,
|
|
StartedTimestamp = DateTime.Now.AddMinutes(-5)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
new Job()
|
|
{
|
|
Name = "Test Failed 2 Job",
|
|
NextRunTime = DateTime.Now.AddHours(-1),
|
|
JobStatus = JobStatus.Processing,
|
|
WorkItems = new List<WorkItem>() {
|
|
new WorkItem()
|
|
{
|
|
Name = "Test Failed 2 WorkItem",
|
|
WorkItemExecutions = new List<WorkItemExecution>(){
|
|
new WorkItemExecution()
|
|
{
|
|
Status = StatusType.Failed,
|
|
StartedTimestamp = DateTime.Now.AddMinutes(-29)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
// Act
|
|
var result = _jobService.GetJobsInStatusLongerThanTimeLimit(jobs, 30);
|
|
|
|
// Assert
|
|
Assert.NotNull(result);
|
|
Assert.Empty(result);
|
|
}
|
|
|
|
[Fact]
|
|
public void GetJobsProcessingLongerThanTime_Return_TwoJobs_MultipleStatuses()
|
|
{
|
|
// Arrange
|
|
var jobs = new List<Job>()
|
|
{
|
|
new Job()
|
|
{
|
|
Name = "Test Failed Job",
|
|
NextRunTime = DateTime.Now.AddHours(-1),
|
|
JobStatus = JobStatus.DeterminingOperation,
|
|
WorkItems = new List<WorkItem>() {
|
|
new WorkItem()
|
|
{
|
|
Name = "Test Failed WorkItem",
|
|
WorkItemExecutions = new List<WorkItemExecution>(){
|
|
new WorkItemExecution()
|
|
{
|
|
Status = StatusType.Failed,
|
|
StartedTimestamp = Convert.ToDateTime("4/1/2021")
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
new Job()
|
|
{
|
|
Name = "Test Failed 2 Job",
|
|
NextRunTime = DateTime.Now.AddHours(-1),
|
|
JobStatus = JobStatus.Processing,
|
|
WorkItems = new List<WorkItem>() {
|
|
new WorkItem()
|
|
{
|
|
Name = "Test Failed 2 WorkItem",
|
|
WorkItemExecutions = new List<WorkItemExecution>(){
|
|
new WorkItemExecution()
|
|
{
|
|
Status = StatusType.Failed,
|
|
StartedTimestamp = DateTime.Now.AddMinutes(-31)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
// Act
|
|
var result = _jobService.GetJobsInStatusLongerThanTimeLimit(jobs, 30);
|
|
|
|
// Assert
|
|
Assert.NotNull(result);
|
|
Assert.Equal(2, result.Count());
|
|
}
|
|
|
|
[Fact]
|
|
public async Task GetErroredAndProcessingJobs_Return_TwoJobs_OneFailed_OneProcessingLongerThen_30minutes()
|
|
{
|
|
var jobs = new List<Job>()
|
|
{
|
|
new Job()
|
|
{
|
|
Name = "Test Pending Job",
|
|
NextRunTime = DateTime.Now.AddHours(-1),
|
|
WorkItems = new List<WorkItem>() {
|
|
new WorkItem()
|
|
{
|
|
Name = "Test Pending WorkItem",
|
|
WorkItemExecutions = new List<WorkItemExecution>(){
|
|
new WorkItemExecution()
|
|
{
|
|
Status = StatusType.Pending,
|
|
StartedTimestamp = Convert.ToDateTime("4/1/2021")
|
|
}
|
|
}
|
|
}
|
|
},
|
|
JobStatus = JobStatus.Failed
|
|
},
|
|
new Job()
|
|
{
|
|
Name = "Test Failed Job",
|
|
NextRunTime = DateTime.Now.AddHours(-1),
|
|
WorkItems = new List<WorkItem>() {
|
|
new WorkItem()
|
|
{
|
|
Name = "Test Failed WorkItem",
|
|
WorkItemExecutions = new List<WorkItemExecution>(){
|
|
new WorkItemExecution()
|
|
{
|
|
Status = StatusType.Failed,
|
|
StartedTimestamp = Convert.ToDateTime("4/1/2021")
|
|
}
|
|
}
|
|
}
|
|
},
|
|
JobStatus = JobStatus.Failed
|
|
},
|
|
new Job()
|
|
{
|
|
Name = "Test Process Job",
|
|
NextRunTime = DateTime.Now.AddHours(-1),
|
|
WorkItems = new List<WorkItem>() {
|
|
new WorkItem()
|
|
{
|
|
Name = "Test Process WorkItem",
|
|
WorkItemExecutions = new List<WorkItemExecution>(){
|
|
new WorkItemExecution()
|
|
{
|
|
Status = StatusType.Processing,
|
|
StartedTimestamp = DateTime.Now.AddMinutes(-31)
|
|
}
|
|
}
|
|
}
|
|
},
|
|
JobStatus = JobStatus.Processing
|
|
}
|
|
};
|
|
|
|
_mockJobRepository.Setup(repo => repo.FindJobsPastDateByStatuses(It.IsAny<DateTime>(), 10, 20, It.IsAny<List<JobStatus>>())).ReturnsAsync(jobs);
|
|
|
|
// Act
|
|
var result = await _jobService.GetErrorMonitoringJobs();
|
|
|
|
// Assert
|
|
Assert.NotNull(result);
|
|
Assert.Equal(3, result.ToList().Count);
|
|
Assert.Single(result.Where(r => r.CurrentStatus == StatusType.Failed));
|
|
Assert.Single(result.Where(r => r.CurrentStatus == StatusType.Processing));
|
|
}
|
|
|
|
[Fact]
|
|
public async Task GetErroredAndProcessingJobs_Return_OneFailedJob()
|
|
{
|
|
var jobs = new List<Job>()
|
|
{
|
|
new Job()
|
|
{
|
|
Name = "Test Pending Job",
|
|
NextRunTime = DateTime.Now.AddHours(-1),
|
|
WorkItems = new List<WorkItem>() {
|
|
new WorkItem()
|
|
{
|
|
Name = "Test Pending WorkItem",
|
|
WorkItemExecutions = new List<WorkItemExecution>(){
|
|
new WorkItemExecution()
|
|
{
|
|
Status = StatusType.Pending,
|
|
StartedTimestamp = DateTime.Now.AddMinutes(-5)
|
|
}
|
|
}
|
|
}
|
|
},
|
|
JobStatus = JobStatus.PendingToRun
|
|
},
|
|
new Job()
|
|
{
|
|
Name = "Test Failed Job",
|
|
NextRunTime = DateTime.Now.AddHours(-1),
|
|
WorkItems = new List<WorkItem>() {
|
|
new WorkItem()
|
|
{
|
|
Name = "Test Failed WorkItem",
|
|
WorkItemExecutions = new List<WorkItemExecution>(){
|
|
new WorkItemExecution()
|
|
{
|
|
Status = StatusType.Failed,
|
|
StartedTimestamp = Convert.ToDateTime("4/1/2021")
|
|
}
|
|
}
|
|
}
|
|
},
|
|
JobStatus = JobStatus.Failed
|
|
},
|
|
new Job()
|
|
{
|
|
Name = "Test Process Job",
|
|
NextRunTime = DateTime.Now.AddHours(-1),
|
|
WorkItems = new List<WorkItem>() {
|
|
new WorkItem()
|
|
{
|
|
Name = "Test Process WorkItem",
|
|
WorkItemExecutions = new List<WorkItemExecution>(){
|
|
new WorkItemExecution()
|
|
{
|
|
Status = StatusType.Processing,
|
|
StartedTimestamp = DateTime.Now.AddMinutes(-5)
|
|
}
|
|
}
|
|
}
|
|
},
|
|
JobStatus = JobStatus.Inactive
|
|
}
|
|
};
|
|
|
|
_mockJobRepository.Setup(repo => repo.FindJobsPastDateByStatuses(It.IsAny<DateTime>(), 10, 20, It.IsAny<List<JobStatus>>())).ReturnsAsync(jobs);
|
|
|
|
// Act
|
|
var result = await _jobService.GetErrorMonitoringJobs();
|
|
|
|
// Assert
|
|
Assert.NotNull(result);
|
|
Assert.Single(result);
|
|
Assert.Single(result.Where(r => r.CurrentStatus == StatusType.Failed));
|
|
Assert.Empty(result.Where(r => r.CurrentStatus == StatusType.Processing));
|
|
}
|
|
|
|
[Fact]
|
|
public async Task GetErroredAndProcessingJobs_Return_Empty()
|
|
{
|
|
var jobs = new List<Job>()
|
|
{
|
|
new Job()
|
|
{
|
|
Name = "Test Pending Job",
|
|
NextRunTime = DateTime.Now.AddHours(-1),
|
|
WorkItems = new List<WorkItem>() {
|
|
new WorkItem()
|
|
{
|
|
Name = "Test Pending WorkItem",
|
|
WorkItemExecutions = new List<WorkItemExecution>(){
|
|
new WorkItemExecution()
|
|
{
|
|
Status = StatusType.Pending,
|
|
StartedTimestamp = DateTime.Now.AddMinutes(-12)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
new Job()
|
|
{
|
|
Name = "Test Process 1 Job",
|
|
NextRunTime = DateTime.Now.AddHours(-1),
|
|
WorkItems = new List<WorkItem>() {
|
|
new WorkItem()
|
|
{
|
|
Name = "Test Process 1 WorkItem",
|
|
WorkItemExecutions = new List<WorkItemExecution>(){
|
|
new WorkItemExecution()
|
|
{
|
|
Status = StatusType.Processing,
|
|
StartedTimestamp = DateTime.Now.AddMinutes(-2)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
new Job()
|
|
{
|
|
Name = "Test Process 2 Job",
|
|
NextRunTime = DateTime.Now.AddHours(-1),
|
|
WorkItems = new List<WorkItem>() {
|
|
new WorkItem()
|
|
{
|
|
Name = "Test Process 2 WorkItem",
|
|
WorkItemExecutions = new List<WorkItemExecution>(){
|
|
new WorkItemExecution()
|
|
{
|
|
Status = StatusType.Processing,
|
|
StartedTimestamp = DateTime.Now.AddMinutes(-5)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
_mockJobRepository.Setup(repo => repo.FindJobsPastDateByStatuses(It.IsAny<DateTime>(), 10, 20, It.IsAny<List<JobStatus>>())).ReturnsAsync(jobs);
|
|
|
|
// Act
|
|
var result = await _jobService.GetErrorMonitoringJobs();
|
|
|
|
// Assert
|
|
Assert.NotNull(result);
|
|
Assert.Empty(result);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task FilterPaged_Ok()
|
|
{
|
|
var pagedJobResult = new PagedResult<Job>();
|
|
|
|
var filter = new Filter()
|
|
{
|
|
Page = 1,
|
|
Limit = 2,
|
|
StatusFilters = null,
|
|
SortableFields = null,
|
|
TagIdFilters = new List<int> { 1 }
|
|
};
|
|
|
|
_mockJobRepository.Setup(repo => repo.FilteredListAsync(filter, _apiConfiguration.NumberOfWorkItemExecutions, _apiConfiguration.NumberOfExecutionMessages))
|
|
.ReturnsAsync(pagedJobResult).Verifiable();
|
|
|
|
// Act
|
|
var result = await _jobService.GetFilteredJobs(filter);
|
|
|
|
// Assert
|
|
Assert.NotNull(result);
|
|
Assert.Equal(pagedJobResult, result);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task DeleteAsync_Success()
|
|
{
|
|
var jobReturned = new Job
|
|
{
|
|
JobId = 1,
|
|
WorkItems = new List<WorkItem>
|
|
{
|
|
new WorkItem
|
|
{
|
|
WorkItemId = 1
|
|
},
|
|
new WorkItem
|
|
{
|
|
WorkItemId = 2
|
|
}
|
|
}
|
|
};
|
|
_mockJobRepository.Setup(repo => repo.FindByIdAsync(1, 10, 20)).ReturnsAsync(jobReturned);
|
|
|
|
// Act
|
|
var jobIdToDelete = 1;
|
|
await _jobService.DeleteAsync(jobIdToDelete);
|
|
|
|
// Assert
|
|
_mockJobRepository.Verify(service => service.FindByIdAsync(It.Is<int>(x => x == 1), It.Is<int>(x => x == 10), It.Is<int>(x => x == 20)), Times.Once);
|
|
_mockWorkItemService.Verify(service => service.DeleteList(It.Is<List<WorkItem>>(workItems => workItems.Count == 2)), Times.Never);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task GetJobsReadyToBeScheduled_Return_Empty()
|
|
{
|
|
var jobs = new List<Job>();
|
|
|
|
_mockJobRepository.Setup(repo => repo.FindJobsReadyToBeScheduled(It.IsAny<DateTime>())).ReturnsAsync(jobs);
|
|
|
|
// Act
|
|
var result = await _jobService.GetJobsReadyToBeScheduled();
|
|
|
|
// Assert
|
|
Assert.NotNull(result);
|
|
Assert.Empty(result);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task GetJobsReadyToBeScheduled_Returns_One()
|
|
{
|
|
var jobs = new List<Job>
|
|
{
|
|
new Job
|
|
{
|
|
JobId = 1,
|
|
}
|
|
};
|
|
|
|
_mockJobRepository.Setup(repo => repo.FindJobsReadyToBeScheduled(It.IsAny<DateTime>())).ReturnsAsync(jobs);
|
|
|
|
// Act
|
|
var result = await _jobService.GetJobsReadyToBeScheduled();
|
|
|
|
// Assert
|
|
Assert.NotNull(result);
|
|
Assert.Single(result);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task GetInactiveAsync_Success()
|
|
{
|
|
// Arrange
|
|
_mockJobRepository.Setup(repo => repo.ListInactiveAsync(10, 20)).ReturnsAsync(new List<Job>()
|
|
{
|
|
new Job(),
|
|
new Job()
|
|
});
|
|
|
|
// Act
|
|
var result = await _jobService.GetInactiveAsync();
|
|
|
|
// Assert
|
|
Assert.NotNull(result);
|
|
Assert.Equal(2, result.Count());
|
|
}
|
|
|
|
[Fact]
|
|
public async Task GetSoftDeletedAsync_Success()
|
|
{
|
|
// Arrange
|
|
_mockJobRepository.Setup(repo => repo.ListSoftDeletedTrackedAsync(10, 20, It.IsAny<DateTime>())).ReturnsAsync(new List<Job>()
|
|
{
|
|
new Job(),
|
|
new Job()
|
|
});
|
|
|
|
// Act
|
|
var result = await _jobService.GetSoftDeletedTrackedAsync(DateTime.Now.AddDays(-1));
|
|
|
|
// Assert
|
|
Assert.NotNull(result);
|
|
Assert.Equal(2, result.Count());
|
|
}
|
|
|
|
[Fact]
|
|
public async Task RemoveSoftDeleteById_Success()
|
|
{
|
|
// Arrange
|
|
var existingJob = new Job()
|
|
{
|
|
JobId = 100,
|
|
SoftDeleteDate = DateTime.Now,
|
|
};
|
|
|
|
_mockJobRepository.Setup(repo => repo.FindByIdAsync(It.IsAny<int>(), 10, 20)).ReturnsAsync(existingJob);
|
|
_mockJobRepository.Setup(repo => repo.Update(It.IsAny<Job>())).Verifiable();
|
|
|
|
// Act
|
|
var result = await _jobService.RemoveSoftDeleteById(100);
|
|
|
|
// Assert
|
|
Assert.NotNull(result);
|
|
Assert.Equal(existingJob.JobId, result.JobId);
|
|
Assert.Null(result.SoftDeleteDate);
|
|
_mockJobRepository.Verify(x => x.FindByIdAsync(It.IsAny<int>(), 10, 20), Times.Once);
|
|
_mockJobRepository.Verify(x => x.Update(It.IsAny<Job>()), Times.Once);
|
|
_mockUnitOfWork.Verify(x => x.CompleteAsync(), Times.Once);
|
|
}
|
|
|
|
[Fact]
|
|
public void RemoveSoftDeleteById_Throws()
|
|
{
|
|
// Arrange
|
|
_mockJobRepository.Setup(repo => repo.FindByIdAsync(It.IsAny<int>(), 10, 20)).ReturnsAsync((Job)null);
|
|
|
|
// Act/Assert
|
|
var result = Assert.ThrowsAsync<ArgumentNullException>(async () => await _jobService.RemoveSoftDeleteById(100));
|
|
}
|
|
|
|
[Fact]
|
|
public async Task GetInactiveExcludeSoftDeletedAsync_Success()
|
|
{
|
|
// Arrange
|
|
_mockJobRepository.Setup(repo => repo.ListInactiveExcludeSoftDeletedTrackedAsync(10, 20)).ReturnsAsync(new List<Job>()
|
|
{
|
|
new Job(),
|
|
new Job()
|
|
});
|
|
|
|
// Act
|
|
var result = await _jobService.GetInactiveExcludeSoftDeletedTrackedAsync();
|
|
|
|
// Assert
|
|
Assert.NotNull(result);
|
|
Assert.Equal(2, result.Count());
|
|
}
|
|
|
|
[Fact]
|
|
public async void CopyJobAsync_Success_KeepEnvironment()
|
|
{
|
|
var job = new Job
|
|
{
|
|
JobId = DateTime.Now.Millisecond,
|
|
CronSchedule = new Guid().ToString(),
|
|
NextRunTime = DateTime.Now.AddHours(1)
|
|
};
|
|
|
|
var request = new CopyJobRequest
|
|
{
|
|
JobId = job.JobId,
|
|
ChangeEnvironment = false
|
|
};
|
|
|
|
var newJob = new Job
|
|
{
|
|
JobId = DateTime.Now.Millisecond + 1
|
|
};
|
|
|
|
_mockJobRepository.Setup(x => x.FindByIdAsync(job.JobId, 10, 20))
|
|
.ReturnsAsync(job).Verifiable();
|
|
_mockJobRepository.Setup(x => x.AddAsync(It.IsAny<Job>()))
|
|
.ReturnsAsync(newJob).Verifiable();
|
|
|
|
var result = await _jobService.CopyJobAsync(request);
|
|
Assert.NotNull(result);
|
|
Assert.Null(result.CronSchedule);
|
|
Assert.Null(result.NextRunTime);
|
|
Assert.NotEqual(request.JobId, result.JobId);
|
|
Assert.Equal(newJob.JobId, result.JobId);
|
|
_mockJobRepository.Verify(x => x.FindByIdAsync(It.IsAny<int>(),
|
|
It.IsAny<int>(),
|
|
It.IsAny<int>()), Times.Once());
|
|
_mockJobRepository.Verify(x => x.AddAsync(It.IsAny<Job>()), Times.Once);
|
|
_mockUnitOfWork.Verify(x => x.CompleteAsync(), Times.Once);
|
|
}
|
|
|
|
[Fact]
|
|
public async void CopyJobAsync_Success_ChangeEnvironment()
|
|
{
|
|
var job = new Job
|
|
{
|
|
JobId = DateTime.Now.Millisecond,
|
|
CronSchedule = new Guid().ToString(),
|
|
NextRunTime = DateTime.Now.AddHours(1)
|
|
};
|
|
|
|
var request = new CopyJobRequest
|
|
{
|
|
JobId = job.JobId,
|
|
ChangeEnvironment = true
|
|
};
|
|
|
|
_mockJobRepository.Setup(x => x.FindByIdAsync(job.JobId, 10, 20))
|
|
.ReturnsAsync(job).Verifiable();
|
|
|
|
var result = await _jobService.CopyJobAsync(request);
|
|
Assert.NotNull(result);
|
|
Assert.Null(result.CronSchedule);
|
|
Assert.Null(result.NextRunTime);
|
|
Assert.Equal(0, result.JobId);
|
|
_mockJobRepository.Verify(x => x.FindByIdAsync(It.IsAny<int>(),
|
|
It.IsAny<int>(),
|
|
It.IsAny<int>()), Times.Once());
|
|
_mockJobRepository.Verify(x => x.AddAsync(It.IsAny<Job>()), Times.Never);
|
|
_mockUnitOfWork.Verify(x => x.CompleteAsync(), Times.Never);
|
|
}
|
|
|
|
[Fact]
|
|
public void CopyJobAsync_Failure_NotFound()
|
|
{
|
|
var request = new CopyJobRequest
|
|
{
|
|
JobId = DateTime.Now.Millisecond
|
|
};
|
|
|
|
Job? jobReturned = null;
|
|
|
|
_mockJobRepository.Setup(x => x.FindByIdAsync(request.JobId, 10, 20))
|
|
.ReturnsAsync(jobReturned).Verifiable();
|
|
|
|
Assert.ThrowsAsync<ServiceException>(async () => await _jobService.CopyJobAsync(request));
|
|
|
|
_mockJobRepository.Verify(x => x.FindByIdAsync(It.IsAny<int>(), It.IsAny<int>(), It.IsAny<int>()), Times.Once);
|
|
_mockUnitOfWork.Verify(x => x.CompleteAsync(), Times.Never);
|
|
}
|
|
|
|
[Fact]
|
|
public void CopyJobAsync_Failure_Exception()
|
|
{
|
|
_mockJobRepository.Setup(x => x.FindByIdAsync(It.IsAny<int>(), It.IsAny<int>(), It.IsAny<int>()))
|
|
.ThrowsAsync(new Exception("Test")).Verifiable();
|
|
|
|
Assert.ThrowsAsync<ServiceException>(async () =>
|
|
await _jobService.CopyJobAsync(It.IsAny<CopyJobRequest>()));
|
|
|
|
_mockJobRepository.Verify(x => x.FindByIdAsync(It.IsAny<int>(), It.IsAny<int>(), It.IsAny<int>()), Times.Never);
|
|
_mockUnitOfWork.Verify(x => x.CompleteAsync(), Times.Never);
|
|
}
|
|
} |