diff --git a/src/Illuminate/Support/Testing/Fakes/QueueFake.php b/src/Illuminate/Support/Testing/Fakes/QueueFake.php index 66d191e90c95..1b99d89d4aa6 100644 --- a/src/Illuminate/Support/Testing/Fakes/QueueFake.php +++ b/src/Illuminate/Support/Testing/Fakes/QueueFake.php @@ -34,6 +34,59 @@ public function assertPushed($job, $callback = null) ); } + /** + * Assert if a job was pushed with chained jobs based on a truth-test callback. + * + * @param string $job + * @param array $expectedChain + * @param callable|null $callback + * @return void + */ + public function assertPushedWithChain($job, $expectedChain = [], $callback = null) + { + PHPUnit::assertTrue( + $this->pushed($job, $callback)->count() > 0, + "The expected [{$job}] job was not pushed." + ); + + PHPUnit::assertTrue( + collect($expectedChain)->count() > 0, + "The expected chain can not be empty." + ); + + $isExpectedChainOfObjects = collect($expectedChain) + ->filter(function ($job) { return is_object($job); }) + ->count() == collect($expectedChain)->count(); + + if ($isExpectedChainOfObjects) + { + $chain = collect($expectedChain)->map(function ($job) { return serialize($job); })->all(); + PHPUnit::assertTrue( + $this->pushed($job, $callback) + ->filter(function ($job) use ($chain) { + return $job->chained == $chain; + })->count() > 0, + "The expected chain was not pushed." + ); + + return; + } + + PHPUnit::assertTrue( + $this->pushed($job, $callback) + ->map(function ($job) { + return $job->chained; + })->map(function ($chain) { + return collect($chain)->map(function ($chainedJob) { + return get_class(unserialize($chainedJob)); + }); + })->filter(function ($chain) use ($expectedChain) { + return $chain == collect($expectedChain); + })->count() > 0, + 'The expected chain was not pushed' + ); + } + /** * Assert if a job was pushed a number of times. * diff --git a/tests/Support/SupportTestingQueueFakeTest.php b/tests/Support/SupportTestingQueueFakeTest.php index 495bb0684d3e..40988ef23ee4 100644 --- a/tests/Support/SupportTestingQueueFakeTest.php +++ b/tests/Support/SupportTestingQueueFakeTest.php @@ -2,6 +2,7 @@ namespace Illuminate\Tests\Support; +use Illuminate\Bus\Queueable; use PHPUnit\Framework\TestCase; use Illuminate\Foundation\Application; use Illuminate\Support\Testing\Fakes\QueueFake; @@ -101,6 +102,112 @@ public function testAssertPushedUsingBulk() $this->fake->assertPushedOn($queue, JobStub::class); $this->fake->assertPushed(JobStub::class, 2); } + + public function testAssertPushedWithChainUsingClassesOrObjectsArray() + { + $this->fake->push(new JobWithChainStub([ + new JobStub + ])); + + $this->fake->assertPushedWithChain(JobWithChainStub::class, [ + JobStub::class + ]); + + $this->fake->assertPushedWithChain(JobWithChainStub::class, [ + new JobStub + ]); + } + + public function testAssertPushedWithChainSameJobDifferentChains() + { + $this->fake->push(new JobWithChainStub([ + new JobStub + ])); + $this->fake->push(new JobWithChainStub([ + new JobStub, + new JobStub + ])); + + $this->fake->assertPushedWithChain(JobWithChainStub::class, [ + JobStub::class, + ]); + + $this->fake->assertPushedWithChain(JobWithChainStub::class, [ + JobStub::class, + JobStub::class + ]); + } + + public function testAssertPushedWithChainUsingCallback() + { + $this->fake->push(new JobWithChainAndParameterStub('first', [ + new JobStub, + new JobStub + ])); + + $this->fake->push(new JobWithChainAndParameterStub('second', [ + new JobStub + ])); + + $this->fake->assertPushedWithChain(JobWithChainAndParameterStub::class, [ + JobStub::class + ], function ($job) { + return $job->parameter == 'second'; + }); + + try { + $this->fake->assertPushedWithChain(JobWithChainAndParameterStub::class, [ + JobStub::class, + JobStub::class, + ], function ($job) { + return $job->parameter == 'second'; + }); + $this->fail(); + } catch (ExpectationFailedException $e) { + $this->assertThat($e, new ExceptionMessage('The expected chain was not pushed')); + } + } + + public function testAssertPushedWithChainErrorHandling() + { + try { + $this->fake->assertPushedWithChain(JobWithChainStub::class, []); + $this->fail(); + } catch (ExpectationFailedException $e) { + $this->assertThat($e, new ExceptionMessage('The expected [Illuminate\Tests\Support\JobWithChainStub] job was not pushed')); + } + + $this->fake->push(new JobWithChainStub([ + new JobStub + ])); + + try { + $this->fake->assertPushedWithChain(JobWithChainStub::class, []); + $this->fail(); + } catch (ExpectationFailedException $e) { + $this->assertThat($e, new ExceptionMessage('The expected chain can not be empty')); + } + + try { + $this->fake->assertPushedWithChain(JobWithChainStub::class, [ + new JobStub, + new JobStub + ]); + $this->fail(); + } catch (ExpectationFailedException $e) { + $this->assertThat($e, new ExceptionMessage('The expected chain was not pushed')); + } + + try { + $this->fake->assertPushedWithChain(JobWithChainStub::class, [ + JobStub::class, + JobStub::class + ]); + $this->fail(); + } catch (ExpectationFailedException $e) { + $this->assertThat($e, new ExceptionMessage('The expected chain was not pushed')); + } + } } class JobStub @@ -110,3 +217,36 @@ public function handle() // } } + +class JobWithChainStub +{ + use Queueable; + + function __construct($chain) + { + $this->chain($chain); + } + + public function handle() + { + // + } +} + +class JobWithChainAndParameterStub +{ + use Queueable; + + public $parameter; + + function __construct($parameter, $chain) + { + $this->parameter = $parameter; + $this->chain($chain); + } + + public function handle() + { + // + } +} \ No newline at end of file