Configure and Test Laravel Task Scheduling

后端 未结 3 1535
栀梦
栀梦 2020-12-17 16:10

Environment

  • Laravel Version : 5.1.45 (LTS)

  • PHP Version : 5.6.1


Description

3条回答
  •  孤城傲影
    2020-12-17 16:32

    Building on Michiel's answer, I've used the methods contained in Illuminate\Console\Scheduling\Event to test if the event is due to run for a given date.

    I've mocked the current date using Carbon::setTestNow() so that any date based logic in the when() and skip() filters will behave as expected.

    use Tests\TestCase;
    use Illuminate\Console\Scheduling\Schedule;
    use Illuminate\Console\Scheduling\Event;
    
    use Cron\CronExpression;
    use Carbon\Carbon;
    
    
    class ScheduleTest extends TestCase {
    
    
        public function testCompanyFeedbackSchedule()
        {
            $event = $this->getCommandEvent('your-command-signature');
    
            $test_date = Carbon::now()->startOfDay()->addHours(8);
    
            for ($i=0; $i < 365; $i++) { 
                $test_date->addDay();
                Carbon::setTestNow($test_date);
    
                // Run the when() & skip() filters
                $filters_pass = $event->filtersPass($this->app);
                // Test that the Cron expression passes
                $date_passes = $this->isEventDue($event);
                $will_run = $filters_pass && $date_passes;
    
                // Should only run on first friday of month
                if ($test_date->format('l') === 'Friday' && $test_date->weekOfMonth === 1) {
                    $this->assertTrue($will_run, 'Task should run on '. $test_date->toDateTimeString());
                } else {
                    $this->assertFalse($will_run, 'Task should not run on '. $test_date->toDateTimeString());
                }
            }
        }
    
    
        /**
         * Get the event matching the given command signature from the scheduler
         * 
         * @param  string  $command_signature
         * 
         * @return Illuminate\Console\Scheduling\Event
         */
        private function getCommandEvent($command_signature)
        {
            $schedule = app()->make(Schedule::class);
    
            $event = collect($schedule->events())->first(function (Event $event) use ($command_signature) {
                return stripos($event->command, $command_signature);
            });
    
            if (!$event) {
                $this->fail('Event for '. $command_signature .' not found');
            }
    
            return $event;
        }
    
    
        /**
         * Determine if the Cron expression passes.
         * 
         * Copied from the protected method Illuminate\Console\Scheduling\Event@isEventDue
         * 
         * @return bool
         */
        private function isEventDue(Event $event)
        {
            $date = Carbon::now();
    
            if ($event->timezone) {
                $date->setTimezone($event->timezone);
            }
    
            return CronExpression::factory($event->expression)->isDue($date->toDateTimeString());
        }
    }
    

提交回复
热议问题