/
githubmirror
/
framework
Обзор
Документация
Войти
/
githubmirror
/
framework
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
13.x
tests/Support/SupportTestingQueueFakeTest.php
903 строки
27 KB
Jason McCreary
[13.x] Mockery cleanup (#61117)
10 авг 2026, 20:23
Не верифицирован
10 авг 2026, 20:23
2ee40ee
Код
Авторство
О чём код?
<?php namespace Illuminate\Tests\Support; use BadMethodCallException; use Illuminate\Bus\Queueable; use Illuminate\Foundation\Application; use Illuminate\Queue\Attributes\Delay; use Illuminate\Queue\CallQueuedClosure; use Illuminate\Queue\Jobs\InspectedJob; use Illuminate\Queue\QueueManager; use Illuminate\Support\Carbon; use Illuminate\Support\Testing\Fakes\QueueFake; use Mockery; use PHPUnit\Framework\ExpectationFailedException; use PHPUnit\Framework\TestCase; class SupportTestingQueueFakeTest extends TestCase { /** * @var \Illuminate\Support\Testing\Fakes\QueueFake */ private $fake; /** * @var \Illuminate\Tests\Support\JobStub */ private $job; protected function setUp(): void { $this->fake = new QueueFake(new Application); $this->job = new JobStub; } public function testAssertPushed() { try { $this->fake->assertPushed(JobStub::class); $this->fail(); } catch (ExpectationFailedException $e) { $this->assertStringContainsString('The expected [Illuminate\Tests\Support\JobStub] job was not pushed.', $e->getMessage()); } $this->fake->push($this->job); $this->fake->assertPushed(JobStub::class); } public function testItCanAssertAgainstDataWithPush() { $data = null; $this->fake->push(JobStub::class, ['foo' => 'bar'], 'redis'); $this->fake->assertPushed(JobStub::class, function ($job, $queue, $jobData) use (&$data) { $data = $jobData; return true; }); $this->assertSame(['foo' => 'bar'], $data); } public function testAssertPushedWithIgnore() { $job = new JobStub; $manager = Mockery::mock(QueueManager::class); $manager->expects('push')->withArgs(function ($passedJob) use ($job) { return $passedJob === $job; }); $fake = new QueueFake(new Application, JobToFakeStub::class, $manager); $fake->push($job); $fake->push(new JobToFakeStub()); $fake->assertNotPushed(JobStub::class); $fake->assertPushed(JobToFakeStub::class); } public function testAssertPushedWithClosure() { $this->fake->push($this->job); $this->fake->assertPushed(function (JobStub $job) { return true; }); } public function testQueueSize() { $this->assertEquals(0, $this->fake->size()); $this->fake->push($this->job); $this->assertEquals(1, $this->fake->size()); } public function testQueueSizeAcceptsUnitEnums() { $this->fake->push($this->job, '', QueueNameEnumStub::Foo); $this->assertEquals(1, $this->fake->size('foo')); $this->assertEquals(1, $this->fake->size(QueueNameEnumStub::Foo)); $this->assertEquals(0, $this->fake->size(QueueNameEnumStub::Bar)); } public function testAssertNotPushed() { $this->fake->push($this->job); try { $this->fake->assertNotPushed(JobStub::class); $this->fail(); } catch (ExpectationFailedException $e) { $this->assertStringContainsString('The unexpected [Illuminate\Tests\Support\JobStub] job was pushed.', $e->getMessage()); } } public function testAssertNotPushedWithClosure() { $this->fake->assertNotPushed(JobStub::class); $this->fake->push($this->job); try { $this->fake->assertNotPushed(function (JobStub $job) { return true; }); $this->fail(); } catch (ExpectationFailedException $e) { $this->assertStringContainsString('The unexpected [Illuminate\Tests\Support\JobStub] job was pushed.', $e->getMessage()); } } public function testAssertPushedOn() { $this->fake->push($this->job, '', 'foo'); try { $this->fake->assertPushedOn('bar', JobStub::class); $this->fake->assertPushedOn(QueueNameEnumStub::Bar, JobStub::class); $this->fail(); } catch (ExpectationFailedException $e) { $this->assertStringContainsString('The expected [Illuminate\Tests\Support\JobStub] job was not pushed.', $e->getMessage()); } $this->fake->assertPushedOn('foo', JobStub::class); $this->fake->assertPushedOn(QueueNameEnumStub::Foo, JobStub::class); } public function testAssertPushedOnWithClosure() { $this->fake->push($this->job, '', 'foo'); try { $this->fake->assertPushedOn('bar', function (JobStub $job) { return true; }); $this->fail(); } catch (ExpectationFailedException $e) { $this->assertStringContainsString('The expected [Illuminate\Tests\Support\JobStub] job was not pushed.', $e->getMessage()); } $this->fake->assertPushedOn('foo', function (JobStub $job) { return true; }); } public function testAssertPushedTimes() { $this->fake->push($this->job); $this->fake->push($this->job); try { $this->fake->assertPushed(JobStub::class, 1); $this->fail(); } catch (ExpectationFailedException $e) { $this->assertStringContainsString('The expected [Illuminate\Tests\Support\JobStub] job was pushed 2 times instead of 1 time.', $e->getMessage()); } $this->fake->assertPushed(JobStub::class, 2); } public function testAssertCount() { $this->fake->push(function () { // Do nothing }); $this->fake->push($this->job); $this->fake->push($this->job); $this->fake->assertCount(3); } public function testAssertNothingPushed() { $this->fake->assertNothingPushed(); $this->fake->push($this->job); $this->fake->push(function () { // }); try { $this->fake->assertNothingPushed(); $this->fail(); } catch (ExpectationFailedException $e) { $this->assertStringContainsString('The following jobs were pushed unexpectedly', $e->getMessage()); $this->assertStringContainsString(get_class($this->job), $e->getMessage()); $this->assertStringContainsString(CallQueuedClosure::class, $e->getMessage()); } } public function testAssertPushedUsingBulk() { $this->fake->assertNothingPushed(); $queue = QueueNameEnumStub::Foo; $this->fake->bulk([ $this->job, new JobStub, ], null, $queue); $this->fake->assertPushedOn('foo', JobStub::class); $this->fake->assertPushedOn($queue, JobStub::class); $this->fake->assertPushed(JobStub::class, 2); } public function testBulkRespectsDelayAttribute() { $this->fake->bulk([ new JobWithDelayAttributeStub, new JobStub, ], ['foo' => 'bar'], 'redis'); $this->assertSame(1, $this->fake->delayedSize('redis')); $this->fake->assertPushedOn('redis', JobWithDelayAttributeStub::class); $this->fake->assertPushed(JobWithDelayAttributeStub::class, function ($job, $queue, $data) { return $queue === 'redis' && $data === ['foo' => 'bar']; }); $this->fake->assertPushedOn('redis', JobStub::class); } public function testBulkRespectsRuntimeDelay() { $job = (new JobWithRuntimeDelayStub)->delay(30); $this->fake->bulk([$job], '', 'redis'); $this->assertSame(1, $this->fake->delayedSize('redis')); $this->fake->assertPushedOn('redis', JobWithRuntimeDelayStub::class); } public function testPushOnAndLaterOnAcceptUnitEnums() { $this->fake->pushOn(QueueNameEnumStub::Foo, $this->job); $this->fake->laterOn(QueueNameEnumStub::Bar, 10, new JobToFakeStub); $this->fake->assertPushedOn('foo', JobStub::class); $this->fake->assertPushedOn('bar', JobToFakeStub::class); } 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 testAssertPushedWithoutChain() { $this->fake->push(new JobWithChainStub([])); $this->fake->assertPushedWithoutChain(JobWithChainStub::class); } 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->assertStringContainsString('The expected chain was not pushed.', $e->getMessage()); } } public function testAssertPushedWithChainErrorHandling() { try { $this->fake->assertPushedWithChain(JobWithChainStub::class, []); $this->fail(); } catch (ExpectationFailedException $e) { $this->assertStringContainsString('The expected [Illuminate\Tests\Support\JobWithChainStub] job was not pushed.', $e->getMessage()); } $this->fake->push(new JobWithChainStub([ new JobStub, ])); try { $this->fake->assertPushedWithChain(JobWithChainStub::class, []); $this->fail(); } catch (ExpectationFailedException $e) { $this->assertStringContainsString('The expected chain can not be empty.', $e->getMessage()); } try { $this->fake->assertPushedWithChain(JobWithChainStub::class, [ new JobStub, new JobStub, ]); $this->fail(); } catch (ExpectationFailedException $e) { $this->assertStringContainsString('The expected chain was not pushed.', $e->getMessage()); } try { $this->fake->assertPushedWithChain(JobWithChainStub::class, [ JobStub::class, JobStub::class, ]); $this->fail(); } catch (ExpectationFailedException $e) { $this->assertStringContainsString('The expected chain was not pushed.', $e->getMessage()); } } public function testCallUndefinedMethodErrorHandling() { try { $this->fake->undefinedMethod(); } catch (BadMethodCallException $e) { $this->assertSame(sprintf( 'Call to undefined method %s::%s()', get_class($this->fake), 'undefinedMethod' ), $e->getMessage()); } } public function testAssertClosurePushed() { $this->fake->push(function () { // Do nothing }); $this->fake->assertClosurePushed(); } public function testAssertClosurePushedWithTimes() { $this->fake->push(function () { // Do nothing }); $this->fake->push(function () { // Do nothing }); $this->fake->assertClosurePushed(2); } public function testAssertClosureNotPushed() { $this->fake->push($this->job); $this->fake->assertClosureNotPushed(); } public function testItDoesntFakeJobsPassedViaExcept() { $job = new JobStub; $manager = Mockery::mock(QueueManager::class); $manager->expects('push')->withArgs(function ($passedJob) use ($job) { return $passedJob === $job; }); $fake = (new QueueFake(new Application, [], $manager))->except(JobStub::class); $fake->push($job); $fake->push(new JobToFakeStub()); $fake->assertNotPushed(JobStub::class); $fake->assertPushed(JobToFakeStub::class); } public function testItCanSerializeAndRestoreJobs() { // confirm that the default behavior is maintained $this->fake->push(new JobWithSerialization('hello')); $this->fake->assertPushed(JobWithSerialization::class, fn ($job) => $job->value === 'hello'); $job = new JobWithSerialization('hello'); $fake = new QueueFake(new Application); $fake->serializeAndRestore(); $fake->push($job); $fake->assertPushed( JobWithSerialization::class, fn ($job) => $job->value === 'hello-serialized-unserialized' ); } public function testItCanInvokeCallbacksBeforeAndAfterPushingFakedJobs() { $steps = []; $this->fake->beforePushing(function ($job, $data, $queue) use (&$steps) { $steps[] = ['before', is_object($job) ? get_class($job) : $job, $data, $queue]; }); $this->fake->beforePushing(function ($job, $data, $queue) use (&$steps) { $steps[] = ['before again', is_object($job) ? get_class($job) : $job, $data, $queue]; }); $this->fake->afterPushing(function ($job, $data, $queue) use (&$steps) { $steps[] = ['after', is_object($job) ? get_class($job) : $job, $data, $queue]; }); $this->fake->afterPushing(function ($job, $data, $queue) use (&$steps) { $steps[] = ['after again', is_object($job) ? get_class($job) : $job, $data, $queue]; }); $this->fake->push($this->job, ['foo' => 'bar'], 'redis'); $this->assertSame([ ['before', JobStub::class, ['foo' => 'bar'], 'redis'], ['before again', JobStub::class, ['foo' => 'bar'], 'redis'], ['after', JobStub::class, ['foo' => 'bar'], 'redis'], ['after again', JobStub::class, ['foo' => 'bar'], 'redis'], ], $steps); } public function testItCanInvokeCallbacksBeforeAndAfterPushingDispatchedJobs() { $job = new JobStub; $steps = []; $manager = Mockery::mock(QueueManager::class); $manager->expects('push')->withArgs(function ($passedJob, $passedData, $passedQueue) use ($job) { return $passedJob === $job && $passedData === ['foo' => 'bar'] && $passedQueue === 'redis'; }); $fake = (new QueueFake(new Application, [], $manager)) ->except(JobStub::class) ->beforePushing(function ($job, $data, $queue) use (&$steps) { $steps[] = ['before', is_object($job) ? get_class($job) : $job, $data, $queue]; }) ->beforePushing(function ($job, $data, $queue) use (&$steps) { $steps[] = ['before again', is_object($job) ? get_class($job) : $job, $data, $queue]; }) ->afterPushing(function ($job, $data, $queue) use (&$steps) { $steps[] = ['after', is_object($job) ? get_class($job) : $job, $data, $queue]; }) ->afterPushing(function ($job, $data, $queue) use (&$steps) { $steps[] = ['after again', is_object($job) ? get_class($job) : $job, $data, $queue]; }); $fake->push($job, ['foo' => 'bar'], 'redis'); $this->assertSame([ ['before', JobStub::class, ['foo' => 'bar'], 'redis'], ['before again', JobStub::class, ['foo' => 'bar'], 'redis'], ['after', JobStub::class, ['foo' => 'bar'], 'redis'], ['after again', JobStub::class, ['foo' => 'bar'], 'redis'], ], $steps); } public function testItCanFakePushedJobsWithClassAndPayload() { $fake = new QueueFake(new Application, ['JobStub']); $this->assertTrue($fake->shouldFakeJob('JobStub')); $fake->push('JobStub', ['job' => 'payload']); $fake->assertPushed('JobStub'); $fake->assertPushed('JobStub', 1); $fake->assertPushed('JobStub', fn ($job, $queue, $payload) => $payload === ['job' => 'payload']); } public function testAssertChainUsingClassesOrObjectsArray() { $job = new JobWithChainStub([ new JobStub, ]); $job->assertHasChain([ JobStub::class, ]); $job->assertHasChain([ new JobStub(), ]); } public function testAssertNoChain() { $job = new JobWithChainStub([]); $job->assertDoesntHaveChain(); } public function testAssertChainErrorHandling() { $job = new JobWithChainStub([ new JobStub, ]); try { $job->assertHasChain([]); $this->fail(); } catch (ExpectationFailedException $e) { $this->assertStringContainsString('The expected chain can not be empty.', $e->getMessage()); } try { $job->assertHasChain([ new JobStub, new JobStub, ]); $this->fail(); } catch (ExpectationFailedException $e) { $this->assertStringContainsString('The job does not have the expected chain.', $e->getMessage()); } try { $job->assertHasChain([ JobStub::class, JobStub::class, ]); $this->fail(); } catch (ExpectationFailedException $e) { $this->assertStringContainsString('The job does not have the expected chain.', $e->getMessage()); } try { $job->assertDoesntHaveChain(); $this->fail(); } catch (ExpectationFailedException $e) { $this->assertStringContainsString('The job has chained jobs.', $e->getMessage()); } } public function testPendingJobs() { $this->fake->push($this->job, '', 'foo'); $this->fake->push(new JobToFakeStub, '', 'bar'); $pending = $this->fake->pendingJobs('foo'); $this->assertCount(1, $pending); $this->assertInstanceOf(InspectedJob::class, $pending->first()); $this->assertIsString($pending->first()->uuid); $this->assertSame(JobStub::class, $pending->first()->name); $this->assertSame(0, $pending->first()->attempts); $this->assertSame('foo', $pending->first()->queue); } public function testPendingJobsAcceptsUnitEnums() { $this->fake->push($this->job, '', QueueNameEnumStub::Foo); $this->fake->push(new JobToFakeStub, '', QueueNameEnumStub::Bar); $pending = $this->fake->pendingJobs(QueueNameEnumStub::Foo); $this->assertCount(1, $pending); $this->assertSame(JobStub::class, $pending->first()->name); } public function testAllPendingJobs() { $this->fake->push($this->job, '', 'foo'); $this->fake->push(new JobToFakeStub, '', 'bar'); $pending = $this->fake->allPendingJobs(); $this->assertCount(2, $pending); $this->assertInstanceOf(InspectedJob::class, $pending->first()); $this->assertCount(2, $pending->pluck('uuid')->unique()); $this->assertTrue($pending->contains(fn ($job) => $job->name === JobStub::class)); $this->assertTrue($pending->contains(fn ($job) => $job->name === JobToFakeStub::class)); } public function testDelayedJobs() { $this->fake->later(10, $this->job, '', 'foo'); $this->fake->later(10, new JobToFakeStub, '', 'bar'); $delayed = $this->fake->delayedJobs('foo'); $this->assertCount(1, $delayed); $this->assertInstanceOf(InspectedJob::class, $delayed->first()); $this->assertIsString($delayed->first()->uuid); $this->assertSame(JobStub::class, $delayed->first()->name); $this->assertSame(0, $delayed->first()->attempts); $this->assertSame('foo', $delayed->first()->queue); } public function testAllDelayedJobs() { $this->fake->later(10, $this->job, '', 'foo'); $this->fake->later(10, new JobToFakeStub, '', 'bar'); $delayed = $this->fake->allDelayedJobs(); $this->assertCount(2, $delayed); $this->assertInstanceOf(InspectedJob::class, $delayed->first()); $this->assertCount(2, $delayed->pluck('uuid')->unique()); $this->assertTrue($delayed->contains(fn ($job) => $job->name === JobStub::class)); $this->assertTrue($delayed->contains(fn ($job) => $job->name === JobToFakeStub::class)); } public function testDelayedSize() { $this->fake->later(10, $this->job, '', 'foo'); $this->fake->later(10, new JobToFakeStub, '', 'bar'); $this->assertSame(1, $this->fake->delayedSize('foo')); $this->assertSame(1, $this->fake->delayedSize('bar')); $this->assertSame(0, $this->fake->delayedSize('baz')); } public function testDelayedJobsAreStillPushed() { $this->fake->later(10, $this->job, '', 'foo'); $this->fake->assertPushedOn('foo', JobStub::class); } public function testCreationTimeOfOldestPendingJob() { Carbon::setTestNow($now = Carbon::now()); $this->assertNull($this->fake->creationTimeOfOldestPendingJob('foo')); $this->fake->push($this->job, '', 'foo'); Carbon::setTestNow($now->copy()->addMinutes(5)); $this->fake->push(new JobToFakeStub, '', 'foo'); $this->assertSame($now->getTimestamp(), $this->fake->creationTimeOfOldestPendingJob('foo')); } public function testReservedJobs() { $this->fake->reserve($this->job, 'foo'); $this->fake->reserve(new JobToFakeStub, 'bar'); $reserved = $this->fake->reservedJobs('foo'); $this->assertCount(1, $reserved); $this->assertInstanceOf(InspectedJob::class, $reserved->first()); $this->assertIsString($reserved->first()->uuid); $this->assertSame(JobStub::class, $reserved->first()->name); $this->assertSame(0, $reserved->first()->attempts); $this->assertSame('foo', $reserved->first()->queue); } public function testAllReservedJobs() { $this->fake->reserve($this->job, 'foo'); $this->fake->reserve(new JobToFakeStub, 'bar'); $reserved = $this->fake->allReservedJobs(); $this->assertCount(2, $reserved); $this->assertInstanceOf(InspectedJob::class, $reserved->first()); $this->assertTrue($reserved->contains(fn ($job) => $job->name === JobStub::class)); $this->assertTrue($reserved->contains(fn ($job) => $job->name === JobToFakeStub::class)); } public function testReservedSize() { $this->fake->reserve($this->job, 'foo'); $this->fake->reserve(new JobToFakeStub, 'bar'); $this->assertSame(1, $this->fake->reservedSize('foo')); $this->assertSame(1, $this->fake->reservedSize('bar')); $this->assertSame(0, $this->fake->reservedSize('baz')); } public function testReservedJobsAreNotPushed() { $this->fake->reserve($this->job, 'foo'); $this->fake->assertNotPushed(JobStub::class); } public function testClearReserved() { $this->fake->reserve($this->job, 'foo'); $this->fake->reserve(new JobToFakeStub, 'bar'); $this->fake->clearReserved(); $this->assertSame(0, $this->fake->reservedSize('foo')); $this->assertSame(0, $this->fake->reservedSize('bar')); } public function testGetRawPushes() { $this->fake->pushRaw('some-payload', null, ['options' => 'yeah']); $this->fake->pushRaw('some-other-payload', 'my-queue', ['options' => 'also yeah']); $actualPushedRaw = $this->fake->rawPushes(); $this->assertEqualsCanonicalizing([ ['payload' => 'some-payload', 'queue' => null, 'options' => ['options' => 'yeah']], ['payload' => 'some-other-payload', 'queue' => 'my-queue', 'options' => ['options' => 'also yeah']], ], $actualPushedRaw); } public function testRawPushesAcceptUnitEnums() { $this->fake->pushRaw('some-payload', QueueNameEnumStub::Foo, ['options' => 'yeah']); $this->assertEqualsCanonicalizing([ ['payload' => 'some-payload', 'queue' => 'foo', 'options' => ['options' => 'yeah']], ], $this->fake->rawPushes()); $pushedRaw = $this->fake->pushedRaw( fn ($payload, $queue, $options) => $payload === 'some-payload' && $queue === 'foo' && $options['options'] === 'yeah' ); $this->assertCount(1, $pushedRaw); } public function testPushedRaw() { $this->fake->pushRaw('some-payload', null, ['options' => 'yeah']); $this->fake->pushRaw('some-other-payload', 'my-queue', ['options' => 'also yeah']); $this->assertCount(2, $this->fake->pushedRaw()); $pushedRaw = $this->fake->pushedRaw(fn ($payload) => $payload === 'some-payload'); $this->assertCount(1, $pushedRaw); $this->assertEqualsCanonicalizing( ['payload' => 'some-payload', 'queue' => null, 'options' => ['options' => 'yeah']], $pushedRaw[0] ); $pushedRaw = $this->fake->pushedRaw( fn ($payload, $queue, $options) => $payload === 'some-other-payload' && $queue === 'my-queue' && $options['options'] === 'also yeah' ); $this->assertCount(1, $pushedRaw); $pushedRaw = $this->fake->pushedRaw(fn ($payload, $queue, $options) => $options === []); $this->assertCount(0, $pushedRaw); } } enum QueueNameEnumStub: string { case Foo = 'foo'; case Bar = 'bar'; } class JobStub { public function handle() { // } } class JobToFakeStub { public function handle() { // } } #[Delay(15)] class JobWithDelayAttributeStub { use Queueable; public function handle() { // } } class JobWithRuntimeDelayStub { use Queueable; public function handle() { // } } class JobWithChainStub { use Queueable; public function __construct($chain) { $this->chain($chain); } public function handle() { // } } class JobWithChainAndParameterStub { use Queueable; public $parameter; public function __construct($parameter, $chain) { $this->parameter = $parameter; $this->chain($chain); } public function handle() { // } } class JobWithSerialization { use Queueable; public function __construct(public $value) { } public function __serialize(): array { return ['value' => $this->value.'-serialized']; } public function __unserialize(array $data): void { $this->value = $data['value'].'-unserialized'; } }