Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Testing @Scheduled in spring

Spring offers the possibility to schedule and execute tasks at specific intervals using annotations, e.g. @Scheduled

Is there a convenient way to unit test this behavior?

Of course I could call the method of the bean myself, but I want to make sure I don't run into problems like multiple executions due to misconfiguration and so on.

Other frameworks offer the possibility to fast forward the time yourself. One example is Activiti where you can call

org.activiti.engine.impl.util.ClockUtil.setCurrentTime(date) 

to fast forward the time used by the framework.

Is there something comparable in Spring?

Essentially what I want to do is something like this in a unit test (run using SpringJUnit4ClassRunner)

@Test public void testTaskScheduling() {    assertThat(someOtherBean.getSomeProperty(), is(equalTo(whatIinitiallyExpect)));    SpringClockUtil.setDate(dateInTwoHours)// This is what I am missing   SpringTaskExecutor.executeAllScheduledTasks() // Also missing    assertThat(someOtherBean.getSomeProperty(), is(equalTo(whatIexpectNow))); } 
like image 368
David Avatar asked Jun 26 '13 18:06

David


People also ask

What is @scheduled in spring?

Spring Core. Spring provides excellent support for both task scheduling and asynchronous method execution based on cron expression using @Scheduled annotation. The @Scheduled annotation can be added to a method along with trigger metadata.

What is @scheduled annotation in spring?

The @EnableScheduling annotation is used to enable the scheduler for your application. This annotation should be added into the main Spring Boot application class file. @SpringBootApplication @EnableScheduling public class DemoApplication { public static void main(String[] args) { SpringApplication.

What is @scheduled in Java?

The schedule (TimerTask task, Date time) method of Timer class is used to schedule the task for execution at the given time. If the time given is in the past, the task is scheduled at that movement for execution.


1 Answers

You can test the actual method execution using the regular JUnit, but to test if the @Scheduled(cron = "0 * * * * *") you specified is correct you can use:

@Test public void testScheduler(){     // to test if a cron expression runs only from Monday to Friday     org.springframework.scheduling.support.CronTrigger trigger =                                        new CronTrigger("0 0 1 * * MON-FRI");     Calendar today = Calendar.getInstance();     today.set(Calendar.DAY_OF_WEEK, Calendar.FRIDAY);      SimpleDateFormat df = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss EEEE");      final Date yesterday = today.getTime();     log.info("Yesterday was : " + df.format(yesterday));     Date nextExecutionTime = trigger.nextExecutionTime(         new TriggerContext() {              @Override             public Date lastScheduledExecutionTime() {                 return yesterday;             }              @Override             public Date lastActualExecutionTime() {                 return yesterday;             }              @Override             public Date lastCompletionTime() {                 return yesterday;             }         });      String message = "Next Execution date: " + df.format(nextExecutionTime);     log.info(message);  } 

Here is the output:

Yesterday was : 2015/11/06 11:41:58 Friday  Next Execution date: 2015/11/09 01:00:00 Monday 

As the last execution (set in the TriggerContext) was a Friday, the next execution will be on the following Monday.

I was fiddling with the Spring api and I found this solution, I hope this helps somebody as it helped me.

like image 183
Fernando Abreu Avatar answered Oct 07 '22 15:10

Fernando Abreu