Files
EmailBill/WebApi.Test/Application/JobApplicationTest.cs

207 lines
6.3 KiB
C#
Raw Normal View History

2026-02-10 17:49:19 +08:00
using Quartz;
using Quartz.Impl.Matchers;
namespace WebApi.Test.Application;
/// <summary>
/// JobApplication 单元测试
/// </summary>
public class JobApplicationTest : BaseApplicationTest
{
private readonly ISchedulerFactory _schedulerFactory;
private readonly IScheduler _scheduler;
private readonly JobApplication _application;
public JobApplicationTest()
{
_schedulerFactory = Substitute.For<ISchedulerFactory>();
_scheduler = Substitute.For<IScheduler>();
_schedulerFactory.GetScheduler().Returns(_scheduler);
2026-02-11 13:00:01 +08:00
_application = new JobApplication(_schedulerFactory);
2026-02-10 17:49:19 +08:00
}
#region GetJobsAsync Tests
[Fact]
public async Task GetJobsAsync_有任务_应返回任务列表()
{
// Arrange
var jobKey1 = new JobKey("Job1");
var jobKey2 = new JobKey("Job2");
var jobKeys = new List<JobKey> { jobKey1, jobKey2 };
var jobDetail1 = Substitute.For<IJobDetail>();
jobDetail1.Description.Returns("测试任务1");
var jobDetail2 = Substitute.For<IJobDetail>();
jobDetail2.Description.Returns("测试任务2");
var trigger1 = Substitute.For<ITrigger>();
trigger1.Key.Returns(new TriggerKey("Trigger1"));
trigger1.Description.Returns("每天运行");
trigger1.GetNextFireTimeUtc().Returns(DateTimeOffset.Now.AddHours(1));
var trigger2 = Substitute.For<ITrigger>();
trigger2.Key.Returns(new TriggerKey("Trigger2"));
trigger2.Description.Returns("每小时运行");
trigger2.GetNextFireTimeUtc().Returns(DateTimeOffset.Now.AddMinutes(30));
_scheduler.GetJobKeys(Arg.Any<GroupMatcher<JobKey>>()).Returns(jobKeys);
_scheduler.GetJobDetail(jobKey1).Returns(jobDetail1);
_scheduler.GetJobDetail(jobKey2).Returns(jobDetail2);
_scheduler.GetTriggersOfJob(jobKey1).Returns(new List<ITrigger> { trigger1 });
_scheduler.GetTriggersOfJob(jobKey2).Returns(new List<ITrigger> { trigger2 });
_scheduler.GetTriggerState(trigger1.Key).Returns(TriggerState.Normal);
_scheduler.GetTriggerState(trigger2.Key).Returns(TriggerState.Normal);
// Act
var result = await _application.GetJobsAsync();
// Assert
result.Should().HaveCount(2);
result[0].Name.Should().Be("Job1");
result[0].JobDescription.Should().Be("测试任务1");
result[0].Status.Should().Be("Normal");
result[1].Name.Should().Be("Job2");
}
[Fact]
public async Task GetJobsAsync_无任务_应返回空列表()
{
// Arrange
_scheduler.GetJobKeys(Arg.Any<GroupMatcher<JobKey>>()).Returns(new List<JobKey>());
// Act
var result = await _application.GetJobsAsync();
// Assert
result.Should().BeEmpty();
}
[Fact]
public async Task GetJobsAsync_任务无触发器_应显示Unknown状态()
{
// Arrange
var jobKey = new JobKey("TestJob");
var jobDetail = Substitute.For<IJobDetail>();
jobDetail.Description.Returns("测试任务");
_scheduler.GetJobKeys(Arg.Any<GroupMatcher<JobKey>>()).Returns(new List<JobKey> { jobKey });
_scheduler.GetJobDetail(jobKey).Returns(jobDetail);
_scheduler.GetTriggersOfJob(jobKey).Returns(new List<ITrigger>());
// Act
var result = await _application.GetJobsAsync();
// Assert
result.Should().HaveCount(1);
result[0].Status.Should().Be("Unknown");
result[0].NextRunTime.Should().Be("无");
}
#endregion
#region ExecuteAsync Tests
[Fact]
public async Task ExecuteAsync_有效任务名_应触发任务执行()
{
// Arrange
var jobName = "TestJob";
// Act
var result = await _application.ExecuteAsync(jobName);
// Assert
result.Should().BeTrue();
await _scheduler.Received(1).TriggerJob(Arg.Is<JobKey>(k => k.Name == jobName));
}
[Fact]
public async Task ExecuteAsync_空任务名_应抛出ValidationException()
{
// Arrange & Act & Assert
await Assert.ThrowsAsync<ValidationException>(() => _application.ExecuteAsync(string.Empty));
}
[Fact]
public async Task ExecuteAsync_空白任务名_应抛出ValidationException()
{
// Arrange & Act & Assert
await Assert.ThrowsAsync<ValidationException>(() => _application.ExecuteAsync(" "));
}
[Fact]
public async Task ExecuteAsync_Null任务名_应抛出ValidationException()
{
// Arrange & Act & Assert
await Assert.ThrowsAsync<ValidationException>(() => _application.ExecuteAsync(null!));
}
#endregion
#region PauseAsync Tests
[Fact]
public async Task PauseAsync_有效任务名_应暂停任务()
{
// Arrange
var jobName = "TestJob";
// Act
var result = await _application.PauseAsync(jobName);
// Assert
result.Should().BeTrue();
await _scheduler.Received(1).PauseJob(Arg.Is<JobKey>(k => k.Name == jobName));
}
[Fact]
public async Task PauseAsync_空任务名_应抛出ValidationException()
{
// Arrange & Act & Assert
await Assert.ThrowsAsync<ValidationException>(() => _application.PauseAsync(string.Empty));
}
[Fact]
public async Task PauseAsync_空白任务名_应抛出ValidationException()
{
// Arrange & Act & Assert
await Assert.ThrowsAsync<ValidationException>(() => _application.PauseAsync(" "));
}
#endregion
#region ResumeAsync Tests
[Fact]
public async Task ResumeAsync_有效任务名_应恢复任务()
{
// Arrange
var jobName = "TestJob";
// Act
var result = await _application.ResumeAsync(jobName);
// Assert
result.Should().BeTrue();
await _scheduler.Received(1).ResumeJob(Arg.Is<JobKey>(k => k.Name == jobName));
}
[Fact]
public async Task ResumeAsync_空任务名_应抛出ValidationException()
{
// Arrange & Act & Assert
await Assert.ThrowsAsync<ValidationException>(() => _application.ResumeAsync(string.Empty));
}
[Fact]
public async Task ResumeAsync_空白任务名_应抛出ValidationException()
{
// Arrange & Act & Assert
await Assert.ThrowsAsync<ValidationException>(() => _application.ResumeAsync(" "));
}
#endregion
}