using Quartz; using Quartz.Impl.Matchers; namespace WebApi.Test.Application; /// /// JobApplication 单元测试 /// public class JobApplicationTest : BaseApplicationTest { private readonly ISchedulerFactory _schedulerFactory; private readonly IScheduler _scheduler; private readonly ILogger _logger; private readonly JobApplication _application; public JobApplicationTest() { _schedulerFactory = Substitute.For(); _scheduler = Substitute.For(); _logger = CreateMockLogger(); _schedulerFactory.GetScheduler().Returns(_scheduler); _application = new JobApplication(_schedulerFactory, _logger); } #region GetJobsAsync Tests [Fact] public async Task GetJobsAsync_有任务_应返回任务列表() { // Arrange var jobKey1 = new JobKey("Job1"); var jobKey2 = new JobKey("Job2"); var jobKeys = new List { jobKey1, jobKey2 }; var jobDetail1 = Substitute.For(); jobDetail1.Description.Returns("测试任务1"); var jobDetail2 = Substitute.For(); jobDetail2.Description.Returns("测试任务2"); var trigger1 = Substitute.For(); trigger1.Key.Returns(new TriggerKey("Trigger1")); trigger1.Description.Returns("每天运行"); trigger1.GetNextFireTimeUtc().Returns(DateTimeOffset.Now.AddHours(1)); var trigger2 = Substitute.For(); trigger2.Key.Returns(new TriggerKey("Trigger2")); trigger2.Description.Returns("每小时运行"); trigger2.GetNextFireTimeUtc().Returns(DateTimeOffset.Now.AddMinutes(30)); _scheduler.GetJobKeys(Arg.Any>()).Returns(jobKeys); _scheduler.GetJobDetail(jobKey1).Returns(jobDetail1); _scheduler.GetJobDetail(jobKey2).Returns(jobDetail2); _scheduler.GetTriggersOfJob(jobKey1).Returns(new List { trigger1 }); _scheduler.GetTriggersOfJob(jobKey2).Returns(new List { 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>()).Returns(new List()); // 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(); jobDetail.Description.Returns("测试任务"); _scheduler.GetJobKeys(Arg.Any>()).Returns(new List { jobKey }); _scheduler.GetJobDetail(jobKey).Returns(jobDetail); _scheduler.GetTriggersOfJob(jobKey).Returns(new List()); // 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(k => k.Name == jobName)); } [Fact] public async Task ExecuteAsync_空任务名_应抛出ValidationException() { // Arrange & Act & Assert await Assert.ThrowsAsync(() => _application.ExecuteAsync(string.Empty)); } [Fact] public async Task ExecuteAsync_空白任务名_应抛出ValidationException() { // Arrange & Act & Assert await Assert.ThrowsAsync(() => _application.ExecuteAsync(" ")); } [Fact] public async Task ExecuteAsync_Null任务名_应抛出ValidationException() { // Arrange & Act & Assert await Assert.ThrowsAsync(() => _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(k => k.Name == jobName)); } [Fact] public async Task PauseAsync_空任务名_应抛出ValidationException() { // Arrange & Act & Assert await Assert.ThrowsAsync(() => _application.PauseAsync(string.Empty)); } [Fact] public async Task PauseAsync_空白任务名_应抛出ValidationException() { // Arrange & Act & Assert await Assert.ThrowsAsync(() => _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(k => k.Name == jobName)); } [Fact] public async Task ResumeAsync_空任务名_应抛出ValidationException() { // Arrange & Act & Assert await Assert.ThrowsAsync(() => _application.ResumeAsync(string.Empty)); } [Fact] public async Task ResumeAsync_空白任务名_应抛出ValidationException() { // Arrange & Act & Assert await Assert.ThrowsAsync(() => _application.ResumeAsync(" ")); } #endregion }