From bbfa7602524e147368b3940ca7655d58476d0623 Mon Sep 17 00:00:00 2001 From: Frank Dixon Date: Wed, 12 May 2021 11:13:31 +1000 Subject: [PATCH] Added new assertDispatchedSync methods to BusFake --- .../Support/Testing/Fakes/BusFake.php | 110 ++++++++++++++++- tests/Support/SupportTestingBusFakeTest.php | 116 ++++++++++++++++++ 2 files changed, 222 insertions(+), 4 deletions(-) diff --git a/src/Illuminate/Support/Testing/Fakes/BusFake.php b/src/Illuminate/Support/Testing/Fakes/BusFake.php index 106b5b1a74b9..7af1af159765 100644 --- a/src/Illuminate/Support/Testing/Fakes/BusFake.php +++ b/src/Illuminate/Support/Testing/Fakes/BusFake.php @@ -42,6 +42,13 @@ class BusFake implements QueueingDispatcher */ protected $commandsAfterResponse = []; + /** + * The commands that have been explicitly dispatched synchronously. + * + * @var array + */ + protected $commandsSync = []; + /** * The batches that have been dispatched. * @@ -82,7 +89,8 @@ public function assertDispatched($command, $callback = null) PHPUnit::assertTrue( $this->dispatched($command, $callback)->count() > 0 || - $this->dispatchedAfterResponse($command, $callback)->count() > 0, + $this->dispatchedAfterResponse($command, $callback)->count() > 0 || + $this->dispatchedSync($command, $callback)->count() > 0, "The expected [{$command}] job was not dispatched." ); } @@ -97,7 +105,8 @@ public function assertDispatched($command, $callback = null) public function assertDispatchedTimes($command, $times = 1) { $count = $this->dispatched($command)->count() + - $this->dispatchedAfterResponse($command)->count(); + $this->dispatchedAfterResponse($command)->count() + + $this->dispatchedSync($command)->count(); PHPUnit::assertSame( $times, $count, @@ -120,7 +129,8 @@ public function assertNotDispatched($command, $callback = null) PHPUnit::assertTrue( $this->dispatched($command, $callback)->count() === 0 && - $this->dispatchedAfterResponse($command, $callback)->count() === 0, + $this->dispatchedAfterResponse($command, $callback)->count() === 0 && + $this->dispatchedSync($command, $callback)->count() === 0, "The unexpected [{$command}] job was dispatched." ); } @@ -184,6 +194,65 @@ public function assertNotDispatchedAfterResponse($command, $callback = null) ); } + /** + * Assert if a job was explicitly dispatched synchronously based on a truth-test callback. + * + * @param string|\Closure $command + * @param callable|int|null $callback + * @return void + */ + public function assertDispatchedSync($command, $callback = null) + { + if ($command instanceof Closure) { + [$command, $callback] = [$this->firstClosureParameterType($command), $command]; + } + + if (is_numeric($callback)) { + return $this->assertDispatchedSyncTimes($command, $callback); + } + + PHPUnit::assertTrue( + $this->dispatchedSync($command, $callback)->count() > 0, + "The expected [{$command}] job was not dispatched synchronously." + ); + } + + /** + * Assert if a job was pushed synchronously a number of times. + * + * @param string $command + * @param int $times + * @return void + */ + public function assertDispatchedSyncTimes($command, $times = 1) + { + $count = $this->dispatchedSync($command)->count(); + + PHPUnit::assertSame( + $times, $count, + "The expected [{$command}] job was synchronously pushed {$count} times instead of {$times} times." + ); + } + + /** + * Determine if a job was dispatched based on a truth-test callback. + * + * @param string|\Closure $command + * @param callable|null $callback + * @return void + */ + public function assertNotDispatchedSync($command, $callback = null) + { + if ($command instanceof Closure) { + [$command, $callback] = [$this->firstClosureParameterType($command), $command]; + } + + PHPUnit::assertCount( + 0, $this->dispatchedSync($command, $callback), + "The unexpected [{$command}] job was dispatched synchronously." + ); + } + /** * Assert if a chain of jobs was dispatched. * @@ -378,6 +447,28 @@ public function dispatchedAfterResponse(string $command, $callback = null) }); } + /** + * Get all of the jobs dispatched synchronously matching a truth-test callback. + * + * @param string $command + * @param callable|null $callback + * @return \Illuminate\Support\Collection + */ + public function dispatchedSync(string $command, $callback = null) + { + if (! $this->hasDispatchedSync($command)) { + return collect(); + } + + $callback = $callback ?: function () { + return true; + }; + + return collect($this->commandsSync[$command])->filter(function ($command) use ($callback) { + return $callback($command); + }); + } + /** * Get all of the pending batches matching a truth-test callback. * @@ -417,6 +508,17 @@ public function hasDispatchedAfterResponse($command) return isset($this->commandsAfterResponse[$command]) && ! empty($this->commandsAfterResponse[$command]); } + /** + * Determine if there are any stored commands for a given class. + * + * @param string $command + * @return bool + */ + public function hasDispatchedSync($command) + { + return isset($this->commandsSync[$command]) && ! empty($this->commandsSync[$command]); + } + /** * Dispatch a command to its appropriate handler. * @@ -444,7 +546,7 @@ public function dispatch($command) public function dispatchSync($command, $handler = null) { if ($this->shouldFakeJob($command)) { - $this->commands[get_class($command)][] = $command; + $this->commandsSync[get_class($command)][] = $command; } else { return $this->dispatcher->dispatchSync($command, $handler); } diff --git a/tests/Support/SupportTestingBusFakeTest.php b/tests/Support/SupportTestingBusFakeTest.php index bb52320c7aad..cb15da7768e5 100644 --- a/tests/Support/SupportTestingBusFakeTest.php +++ b/tests/Support/SupportTestingBusFakeTest.php @@ -75,6 +75,41 @@ public function testAssertDispatchedAfterResponseClosure() } } + public function testAssertDispatchedSync() + { + try { + $this->fake->assertDispatchedSync(BusJobStub::class); + $this->fail(); + } catch (ExpectationFailedException $e) { + $this->assertThat($e, new ExceptionMessage('The expected [Illuminate\Tests\Support\BusJobStub] job was not dispatched synchronously.')); + } + + $this->fake->dispatch(new BusJobStub); + + try { + $this->fake->assertDispatchedSync(BusJobStub::class); + $this->fail(); + } catch (ExpectationFailedException $e) { + $this->assertThat($e, new ExceptionMessage('The expected [Illuminate\Tests\Support\BusJobStub] job was not dispatched synchronously.')); + } + + $this->fake->dispatchSync(new BusJobStub); + + $this->fake->assertDispatchedSync(BusJobStub::class); + } + + public function testAssertDispatchedSyncClosure() + { + try { + $this->fake->assertDispatchedSync(function (BusJobStub $job) { + return true; + }); + $this->fail(); + } catch (ExpectationFailedException $e) { + $this->assertThat($e, new ExceptionMessage('The expected [Illuminate\Tests\Support\BusJobStub] job was not dispatched synchronously.')); + } + } + public function testAssertDispatchedNow() { $this->fake->dispatchNow(new BusJobStub); @@ -112,6 +147,21 @@ public function testAssertDispatchedAfterResponseWithCallbackInt() $this->fake->assertDispatchedAfterResponse(BusJobStub::class, 2); } + public function testAssertDispatchedSyncWithCallbackInt() + { + $this->fake->dispatchSync(new BusJobStub); + $this->fake->dispatchSync(new BusJobStub); + + try { + $this->fake->assertDispatchedSync(BusJobStub::class, 1); + $this->fail(); + } catch (ExpectationFailedException $e) { + $this->assertThat($e, new ExceptionMessage('The expected [Illuminate\Tests\Support\BusJobStub] job was synchronously pushed 2 times instead of 1 times.')); + } + + $this->fake->assertDispatchedSync(BusJobStub::class, 2); + } + public function testAssertDispatchedWithCallbackFunction() { $this->fake->dispatch(new OtherBusJobStub); @@ -158,6 +208,29 @@ public function testAssertDispatchedAfterResponseWithCallbackFunction() }); } + public function testAssertDispatchedSyncWithCallbackFunction() + { + $this->fake->dispatchSync(new OtherBusJobStub); + $this->fake->dispatchSync(new OtherBusJobStub(1)); + + try { + $this->fake->assertDispatchedSync(OtherBusJobStub::class, function ($job) { + return $job->id === 0; + }); + $this->fail(); + } catch (ExpectationFailedException $e) { + $this->assertThat($e, new ExceptionMessage('The expected [Illuminate\Tests\Support\OtherBusJobStub] job was not dispatched synchronously.')); + } + + $this->fake->assertDispatchedSync(OtherBusJobStub::class, function ($job) { + return $job->id === null; + }); + + $this->fake->assertDispatchedSync(OtherBusJobStub::class, function ($job) { + return $job->id === 1; + }); + } + public function testAssertDispatchedTimes() { $this->fake->dispatch(new BusJobStub); @@ -188,6 +261,21 @@ public function testAssertDispatchedAfterResponseTimes() $this->fake->assertDispatchedAfterResponseTimes(BusJobStub::class, 2); } + public function testAssertDispatchedSyncTimes() + { + $this->fake->dispatchSync(new BusJobStub); + $this->fake->dispatchSync(new BusJobStub); + + try { + $this->fake->assertDispatchedSyncTimes(BusJobStub::class, 1); + $this->fail(); + } catch (ExpectationFailedException $e) { + $this->assertThat($e, new ExceptionMessage('The expected [Illuminate\Tests\Support\BusJobStub] job was synchronously pushed 2 times instead of 1 times.')); + } + + $this->fake->assertDispatchedSyncTimes(BusJobStub::class, 2); + } + public function testAssertNotDispatched() { $this->fake->assertNotDispatched(BusJobStub::class); @@ -246,6 +334,34 @@ public function testAssertNotDispatchedAfterResponseClosure() } } + public function testAssertNotDispatchedSync() + { + $this->fake->assertNotDispatchedSync(BusJobStub::class); + + $this->fake->dispatchSync(new BusJobStub); + + try { + $this->fake->assertNotDispatchedSync(BusJobStub::class); + $this->fail(); + } catch (ExpectationFailedException $e) { + $this->assertThat($e, new ExceptionMessage('The unexpected [Illuminate\Tests\Support\BusJobStub] job was dispatched synchronously.')); + } + } + + public function testAssertNotDispatchedSyncClosure() + { + $this->fake->dispatchSync(new BusJobStub); + + try { + $this->fake->assertNotDispatchedSync(function (BusJobStub $job) { + return true; + }); + $this->fail(); + } catch (ExpectationFailedException $e) { + $this->assertThat($e, new ExceptionMessage('The unexpected [Illuminate\Tests\Support\BusJobStub] job was dispatched synchronously.')); + } + } + public function testAssertDispatchedWithIgnoreClass() { $dispatcher = m::mock(QueueingDispatcher::class);