Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[9.x] Implement except method for fake classes to define what should not be faked #44117

Merged
merged 5 commits into from
Sep 13, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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)
mateusjunges marked this conversation as resolved.
Show resolved Hide resolved
{
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