如何在 Spring 引导应用程序中测试 Quartz 作业的正常工作

How to test proper working of Quartz job in Spring Boot application

我想测试一下我的 Quartz 触发器是否像它在实践中设想的那样工作。 我的 Quartz 配置如下:

@Configuration
public class QuartzConfiguration {

  @Bean
  public JobDetail verificationTokenRemoverJobDetails() {
    return
        JobBuilder
            .newJob(VerificationTokenQuartzRemoverJob.class)
            .withIdentity("Job for verification token remover")
            .storeDurably()
            .build();
  }

  @Bean
  public Trigger verificationTokenRemoverJobTrigger(JobDetail jobADetails) {
    return
        TriggerBuilder
            .newTrigger()
            .forJob(jobADetails)
            .withIdentity("Trigger for verification token remover")
            .withSchedule(CronScheduleBuilder.cronSchedule("0 0 0/2 1/1 * ? *"))
            .build();
  }
}

我的工作 class 看起来像:

@AllArgsConstructor
public class VerificationTokenQuartzRemoverJob implements Job {

  private VerificationTokenRepository verificationTokenRepository;

  @Override
  public void execute(JobExecutionContext context) {
    verificationTokenRepository.deleteAllByCreatedLessThan(LocalDateTime.now().minusMinutes(30));
  }
}

当我在日志中启动我的 Spring 引导应用程序时,我可以意识到作业正在运行并周期性触发,但这不足以确认正常运行。

这就是我决定创建 JUnit 测试的原因。我找到了一个教程:click but an owner used a clause while(true) which according to this topic: click is not a preferred option。这里出现一个问题,是否有任何其他选项来验证 Job class 名称,触发器的身份并检查是否尽可能频繁地调用 CRON 表达式和具体作业?

如果可能的话,我将不胜感激关于如何达到理想效果的建议。

使用 SpringBoot,您可以更轻松地执行以下操作

--- 选项 1 ---

@Configuration
// This is important!
@EnableScheduling
public class Configuration{
 // TODO Change to 0 0 0/2 1/1 * ? *
 @Scheduled(cron = "0 15 10 15 * ?")
 public void scheduleTaskUsingCronExpression() {

    long now = System.currentTimeMillis() / 1000;
     System.out.println(
        "schedule tasks using cron jobs - " + now);
  }      

}

完整示例: https://www.baeldung.com/spring-scheduled-tasks

--- 选项 2-> 以编程方式 ---

@Configuration
@EnableScheduling

public class Configuration implements SchedulingConfigurer {
   @Bean(destroyMethod = "shutdown")
   public Executor taskExecutor() {
      return Executors.newScheduledThreadPool(100);
   }

    @Override
            public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
            CronTrigger cronTrigger
            = new CronTrigger("* * * * * *");

                    taskRegistrar.setScheduler(taskExecutor());
                    taskRegistrar.addTriggerTask(
                            new Runnable() {
                                @Override public void run() {
                                    System.out.println("RUN!!!");
                                }
                            },
                            cronTrigger
                    );
                }

}

请注意,上面关于使用 Spring 调度的答案有一个很大的缺点:如果您只是 运行 您的应用程序的单个实例,这会很好地工作,但是一旦您扩展对于多个实例,它变得更加复杂: 您可能希望 运行 作业仅在特定时间间隔执行一次,但如果两个节点同时 运行,则作业可能会在两个节点上 运行(基本上是两次)。 Quartz 可以处理这些情况,因为它可以有一个中央数据库,如果作业已经开始,它可以通过该数据库进行协调。 使用 spring 调度作业将在两个节点上 运行。