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

[5.6] Non faked events should be properly dispatched #25185

Merged
merged 1 commit into from
Aug 13, 2018

Conversation

X-Coder264
Copy link
Contributor

Currently the EventFake can receive an array of events which should be faked. If you specify exactly which events should be faked, I'd expect that all other events should be properly dispatched and their listeners executed. That's currently not the case as the EventFake listen and subscribe methods do nothing.

I stumbled upon this problem when I was writing some tests:

Event::fake([FoobarEvent::class]);

$user = factory(User::class)->create();

// rest of the test

In this case I have an observer on the User model which creates a "slug" for the model. So when doing User::observe([UserObserver::class]); this gets called

static::$dispatcher->listen("eloquent.{$event}: {$name}", $callback);

As the dispatcher is now the EventFake instance and the listen method in it does nothing my observer listeners weren't registered. This resulted in a

Illuminate\Database\QueryException: SQLSTATE[HY000]: General error: 1364 Field 'slug' doesn't have a default value

exception when the above test was run which I totally didn't expect since I explicitly told the faker that I want only FoobarEvent to be faked.

I fixed this to behave as expected and I also added a test for it.

@taylorotwell taylorotwell merged commit 099b79a into laravel:5.6 Aug 13, 2018
@X-Coder264 X-Coder264 deleted the event-fake-fix branch August 13, 2018 14:53
@paulredmond
Copy link
Contributor

paulredmond commented Aug 24, 2018

Looking at this for a quick 5.6.34 release post on Laravel News, I noticed this message in the documentation which is no longer seems accurate as far as listeners are concerned:

image

@paulredmond
Copy link
Contributor

paulredmond commented Aug 24, 2018

I guess this phrase in the documentation might be inaccurate now too?

As an alternative to mocking, you may use the Event facade's fake method to prevent all event listeners from executing.

I'd gladly try to help update the doc, but I am a little confused myself as to the correct verbiage now that listeners are executed 🤔

@X-Coder264
Copy link
Contributor Author

@paulredmond When doing Event::fake() all events get faked which means that no listeners get executed which means that the documentation that you posted above is still correct.

If you take a look at the EventFake dispatch method you'll see

if ($this->shouldFakeEvent($name, $payload)) {
            $this->events[$name][] = func_get_args();
        } else {
            $this->dispatcher->dispatch($event, $payload, $halt);
 }

So when doing Event::fake() without providing any event to it all listeners are still gonna be faked since the event won't be dispatched. If you call Event::fake(FoobarEvent::class) then FoobarEvent is going to be the only event that is gonna be faked and all other event listeners will be executed normally.

@paulredmond
Copy link
Contributor

@X-Coder264 thanks, that makes sense now 😆

@slakbal
Copy link

slakbal commented Aug 25, 2018

Maybe a fakeAll() method to be explicit that everything is faked, or fakeAllExcept([])?

@mkarnicki
Copy link

@slakbal I doubt Taylor would fancy that, considering there's a couple other facades using ::fake() consistently. Also, fakeAllExcept() (with no arguments) would look bad IMHO.

@robsonvn
Copy link

Docs should be updated after this merge right ?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants