Тестирование триггера Quartz CronTrigger

Предполагая, что у меня есть CronTriggerBean, аналогичный

<bean id="midMonthCronTrigger" class="org.springframework.scheduling.quartz.CronTriggerBean">
    <property name="jobDetail" ref="reminderJobDetail" />
    <property name="cronExpression" value="0 0 6 15W * ?" />
</bean>

Каков наилучший способ проверить, что этот bean будет фактически запускаться в указанную дату, то есть в будний день, ближайший к 15-му числу каждого месяца в 6 часов утра?


Обновление. Предполагается, что это unit test, поэтому я не буду запускать виртуальную машину или менять системное время.

Ответ 1

Хорошо, во-первых, нет смысла тестировать CronTriggerBean. Он является частью структуры spring и уже был протестирован.

Лучшим тестом может быть проверка того, что ваше выражение cron - это то, что вы ожидаете. Один из вариантов заключается в использовании класса Quartz CronExpression. Учитывая объект CronExpression, вы можете вызвать getNextValidTimeAfter(Date), который возвращается в следующий раз после указанной даты, когда выражение будет срабатывать.

Ответ 2

Я использовал CronMaker только для того, чтобы убедиться, что моя экспрессия cron хорошо сформирована, проверьте это: http://www.cronmaker.com/

Ответ 3

  • Вы всегда можете подождать до 15 июля.
  • Быть более серьезным... Если это действительно ключевая часть приложения, и мне нужно его полностью протестировать. Я бы рекомендовал использовать некоторые настройки виртуализации и установить приложение на какой-либо гостевой машине. Затем вы можете играть с системными часами и тестировать разные даты/время, не тратя на него целый месяц. Кроме того, ничего, что должно было бы остановить вас от автоматизации таких тестов.

Ответ 4

Для тех, кто не использует планировщик Quartz, но вместо этого используйте TaskSchedular напрямую:

CronSequenceGenerator generator = new CronSequenceGenerator("0 0 8 */1 * *");
Date next = generator.next(prev);

Ответ 5

Вы также можете получить триггер bean от spring и вызвать метод getFireTimeAfter для завершения.

Ответ 6

Я нашел здесь прохладную документацию о тестировании CronExpression: http://www.nurkiewicz.com/2012/10/testing-quartz-cron-expressions.html

Реализация С# будет примерно такой:

void Run()
{
    //var collection = findTriggerTimesRecursive(new CronExpression("0 0 17 L-3W 6-9 ? *"), DateTime.UtcNow);
    var collection = findTriggerTimesRecursive(new CronExpression("0 0/15 * 1/1 * ? *"), DateTime.UtcNow);
    Console.WriteLine(DateTime.UtcNow);
    foreach (var item in collection)
    {
        Console.WriteLine(item);
    }
}

public List<DateTimeOffset> findTriggerTimesRecursive(CronExpression expr, DateTimeOffset from, int max = 10)
{
    var times = new List<DateTimeOffset>();
    var next = expr.GetNextValidTimeAfter(from);

    while (next != null && times.Count < max)
    {
        times.Add(next.Value);
        from = next.Value;
        next = expr.GetNextValidTimeAfter(from);
    }

    return times;
}

Это классная демонстрация. Но в конце я заканчиваю использование Simple Schedule.

var trigger = TriggerBuilder.Create()
    .WithIdentity("trigger3", "group1")
    .WithSimpleSchedule(
        x =>
        {
            x.WithIntervalInMinutes(15);
            x.RepeatForever();
        }
    )
    .ForJob("myJob", "group1")
    .Build();

Потому что это выполняется немедленно, а затем каждые x времени.