簡體   English   中英

使用 cron 屬性在 Spring-boot 中測試 @Scheduled 函數

[英]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);
    }
}

如果出現以下情況,測試將失敗:

  • @Scheduled 或 @EnableScheduling 未設置
  • cron 表達式不准確
  • 類名和方法名不對應請注意,如果不是樣本,我會將測試格式化為更易讀的格式

我試圖完全按照 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 成功找到我的計划任務。

想想你真正想要測試什么

  1. 我認為您不應該測試@Scheduled是否在做它應該做的事情。 這個測試應該是 spring 框架的一部分,你不應該關心測試框架。

  2. 如果您正確應用@Scheduled可能是一個有意義的測試,並且 Ben Ooms 的答案提供了解決方案。 但是,您很可能正確地應用了它,一旦您在開發模式下運行您的應用程序,很可能會看到它是否有效。

  3. 更重要的測試,如果你的cron規范正確建模領域的需求

    a) 在我看來,它更重要,因為它很容易搞砸,因為它沒有對每個值都有明確的表示法,並且與 UNIX cron 作業不同。 測試可以采用指定的注釋值並檢查它是否對域需求建模,即您的0 0 1 1 * -String 實際上意味着executed at 1 January 00:00 of each year

    b) 另一種測試方法是在測試期間操縱Clock以將其顯式設置為預期時間並查看調度程序是否觸發該方法。 然而,這可能無法捕獲所有情況——尤其是誤報(即調度程序可能會在預期的時刻觸發,但也會在其他不應該觸發的時刻觸發)。

  4. 更重要的是測試調度的方法實際上做了它應該做的事情 這可以是一個簡單的單元測試,但可能涉及集成測試,具體取決於域需求。 單元測試完全獨立於調度機制,因此可以像任何其他單元測試一樣實現(例如使用模擬運行器)。

我認為 3) 可能重要或不那么重要,具體取決於用例,而 4)始終非常重要 因此,兩者都應該是測試策略的一部分。 另一方面,1) 不應該被測試,2) 很好,但可能是過度設計測試。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM