Skip to content

Commit

Permalink
[9.x] Implement except method for fake classes to define what shoul…
Browse files Browse the repository at this point in the history
…d not be faked (#44117)

* Implement `except` for `Queue::fake`

* fix typo

* Implement `except` for `Event::fake`

* apply ci fixes

* formatting

Co-authored-by: Taylor Otwell <[email protected]>
  • Loading branch information
mateusjunges and taylorotwell authored Sep 13, 2022
1 parent 93ff1bc commit 7996b8a
Show file tree
Hide file tree
Showing 4 changed files with 127 additions and 2 deletions.
51 changes: 50 additions & 1 deletion src/Illuminate/Support/Testing/Fakes/EventFake.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,14 @@ class EventFake implements Dispatcher
*
* @var array
*/
protected $eventsToFake;
protected $eventsToFake = [];

/**
* The event types that should be dispatched instead of intercepted.
*
* @var array
*/
protected $eventsToDispatch = [];

/**
* All of the events that have been intercepted keyed by type.
Expand All @@ -49,6 +56,22 @@ public function __construct(Dispatcher $dispatcher, $eventsToFake = [])
$this->eventsToFake = Arr::wrap($eventsToFake);
}

/**
* Specify the events that should be dispatched instead of faked.
*
* @param array|string $eventsToDispatch
* @return $this
*/
public function except($eventsToDispatch)
{
$this->eventsToDispatch = array_merge(
$this->eventsToDispatch,
Arr::wrap($eventsToDispatch)
);

return $this;
}

/**
* Assert if an event has a listener attached to it.
*
Expand Down Expand Up @@ -283,6 +306,10 @@ public function dispatch($event, $payload = [], $halt = false)
*/
protected function shouldFakeEvent($eventName, $payload)
{
if ($this->shouldDispatchEvent($eventName, $payload)) {
return false;
}

if (empty($this->eventsToFake)) {
return true;
}
Expand All @@ -296,6 +323,28 @@ protected function shouldFakeEvent($eventName, $payload)
->isNotEmpty();
}

/**
* Determine whether an event should be dispatched or not.
*
* @param string $eventName
* @param mixed $payload
* @return bool
*/
protected function shouldDispatchEvent($eventName, $payload)
{
if (empty($this->eventsToDispatch)) {
return false;
}

return collect($this->eventsToDispatch)
->filter(function ($event) use ($eventName, $payload) {
return $event instanceof Closure
? $event($eventName, $payload)
: $event === $eventName;
})
->isNotEmpty();
}

/**
* Remove a set of listeners from the dispatcher.
*
Expand Down
44 changes: 43 additions & 1 deletion src/Illuminate/Support/Testing/Fakes/QueueFake.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,17 @@ class QueueFake extends QueueManager implements Queue
/**
* The job types that should be intercepted instead of pushed to the queue.
*
* @var array
* @var \Illuminate\Support\Collection
*/
protected $jobsToFake;

/**
* The job types that should be pushed to the queue and not intercepted.
*
* @var \Illuminate\Support\Collection
*/
protected $jobsToBeQueued;

/**
* All of the jobs that have been pushed.
*
Expand All @@ -48,9 +55,23 @@ public function __construct($app, $jobsToFake = [], $queue = null)
parent::__construct($app);

$this->jobsToFake = Collection::wrap($jobsToFake);
$this->jobsToBeQueued = Collection::make();
$this->queue = $queue;
}

/**
* Specify the jobs that should be queued instead of faked.
*
* @param array|string $jobsToBeQueued
* @return $this
*/
public function except($jobsToBeQueued)
{
$this->jobsToBeQueued = Collection::wrap($jobsToBeQueued)->merge($this->jobsToBeQueued);

return $this;
}

/**
* Assert if a job was pushed based on a truth-test callback.
*
Expand Down Expand Up @@ -323,6 +344,10 @@ public function push($job, $data = '', $queue = null)
*/
public function shouldFakeJob($job)
{
if ($this->shouldDispatchJob($job)) {
return false;
}

if ($this->jobsToFake->isEmpty()) {
return true;
}
Expand All @@ -332,6 +357,23 @@ public function shouldFakeJob($job)
);
}

/**
* Determine if a job should be pushed to the queue instead of faked.
*
* @param object $job
* @return bool
*/
protected function shouldDispatchJob($job)
{
if ($this->jobsToBeQueued->isEmpty()) {
return false;
}

return $this->jobsToBeQueued->contains(
fn ($jobToQueue) => $job instanceof ((string) $jobToQueue)
);
}

/**
* Push a raw payload onto the queue.
*
Expand Down
16 changes: 16 additions & 0 deletions tests/Integration/Events/EventFakeTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,22 @@ public function testFakeExceptAllowsGivenEventsToBeDispatched()
Event::assertNotDispatched('non-fake-event');
}

public function testEventsListedInExceptAreProperlyDispatched()
{
Event::fake()->except('important-event');

Event::listen('test', function () {
return 'test';
});

Event::listen('important-event', function () {
return 'important';
});

$this->assertEquals(null, Event::dispatch('test'));
$this->assertEquals(['important'], Event::dispatch('important-event'));
}

public function testAssertListening()
{
Event::fake();
Expand Down
18 changes: 18 additions & 0 deletions tests/Support/SupportTestingQueueFakeTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -328,6 +328,24 @@ public function testCallUndefinedMethodErrorHandling()
)));
}
}

public function testItDoesntFakeJobsPassedViaExcept()
{
$job = new JobStub;

$manager = m::mock(QueueManager::class);
$manager->shouldReceive('push')->once()->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);
}
}

class JobStub
Expand Down

0 comments on commit 7996b8a

Please sign in to comment.