[英]Spring-Boot @Scheduled Cron expressions to make slight delay between two tasks?
[英]Test a @Scheduled function in Spring-boot with cron property
我想测试我的 Cron-job 是否会在给定时间(每年 1 月 1 日 00:00)执行。 有没有办法测试这个? 不幸的是,我在网上找到的每个示例都指的是将在修复期后执行的作业,例如所有 5 秒。( https://www.baeldung.com/spring-testing-scheduled-annotation )。
@Scheduled(cron = " 0 0 1 1 *")
public void myFunc() {
do something
}
好吧,如果您真的想测试执行情况,您将不得不在新年前夕监视应用程序;<)
如果您想测试调度是否已正确设置并且您的任务是否已调度,那么您可以自动装配 ScheduledStaskHolder 并查询您的任务。 假设这个实现:
package nl.benooms.scheduledannotationplayground;
@Service
public class FixedDateSchedule {
@Scheduled(cron = "0 0 0 1 1 *")
public void OnceAYearCron() {
System.out.println("yearly");
}
}
那么测试可能是:
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE)
class FixedDateScheduleTest {
@Autowired
private ScheduledTaskHolder scheduledTaskHolder;
@Test
public void testYearlyCronTaskScheduled() {
Set<ScheduledTask> scheduledTasks = scheduledTaskHolder.getScheduledTasks();
scheduledTasks.forEach(scheduledTask -> scheduledTask.getTask().getRunnable().getClass().getDeclaredMethods());
long count = scheduledTasks.stream()
.filter(scheduledTask -> scheduledTask.getTask() instanceof CronTask)
.map(scheduledTask -> (CronTask) scheduledTask.getTask())
.filter(cronTask -> cronTask.getExpression().equals("0 0 0 1 1 *") && cronTask.toString().equals("nl.benooms.scheduledannotationplayground.FixedDateSchedule.OnceAYearCron"))
.count();
assertThat(count).isEqualTo(1L);
}
}
如果出现以下情况,测试将失败:
我试图完全按照 Ben Ooms 的建议去做,但它对我不起作用。
我没有使用注释设置我的计划任务,我已经实施了一种解决方法来使用自动装配的“TaskScheduler”来安排它们,尽管它正在工作,但我无法在 ScheduledTaskHolder 中找到我的计划任务。
原来我必须声明一个 Bean 像:
@Configuration
class SchedulerConfiguration {
@Bean
fun threadPoolTaskScheduler(): TaskScheduler {
val scheduler = ThreadPoolTaskScheduler()
scheduler.poolSize = 20
return scheduler
}
}
并使用接口安排我的任务: SchedulingConfigurer
:
class MySchedulers(
private val myService: MyService,
@Qualifier("threadPoolTaskScheduler") private val threadPoolTaskScheduler: TaskScheduler
) : SchedulingConfigurer {
private val logger = Logger(this::class.java)
private val cronExpression = "0 0 10 * * *"
override fun configureTasks(taskRegistrar: ScheduledTaskRegistrar) {
taskRegistrar.setTaskScheduler(threadPoolTaskScheduler)
logger.info("Setting scheduler cron=$cronExpression")
taskRegistrar.addCronTask(CronTask({ runMyTask() }, CronTrigger(cronExpression)))
}
}
private fun runMyTask() {
myService.update()
}
}
然后我可以按照 Ben Ooms 的建议使用 ScheduledTaskHolder 成功找到我的计划任务。
想想你真正想要测试什么。
我认为您不应该测试@Scheduled
是否在做它应该做的事情。 这个测试应该是 spring 框架的一部分,你不应该关心测试框架。
如果您正确应用@Scheduled
可能是一个有意义的测试,并且 Ben Ooms 的答案提供了解决方案。 但是,您很可能正确地应用了它,一旦您在开发模式下运行您的应用程序,很可能会看到它是否有效。
更重要的测试,如果你的cron
规范正确建模领域的需求。
a) 在我看来,它更重要,因为它很容易搞砸,因为它没有对每个值都有明确的表示法,并且与 UNIX cron 作业不同。 测试可以采用指定的注释值并检查它是否对域需求建模,即您的0 0 1 1 *
-String 实际上意味着executed at 1 January 00:00 of each year
。
b) 另一种测试方法是在测试期间操纵Clock
以将其显式设置为预期时间并查看调度程序是否触发该方法。 然而,这可能无法捕获所有情况——尤其是误报(即调度程序可能会在预期的时刻触发,但也会在其他不应该触发的时刻触发)。
更重要的是:测试调度的方法实际上做了它应该做的事情。 这可以是一个简单的单元测试,但可能涉及集成测试,具体取决于域需求。 单元测试完全独立于调度机制,因此可以像任何其他单元测试一样实现(例如使用模拟运行器)。
我认为 3) 可能重要或不那么重要,具体取决于用例,而 4)始终非常重要。 因此,两者都应该是测试策略的一部分。 另一方面,1) 不应该被测试,2) 很好,但可能是过度设计测试。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.