How can I prevent laravel from firing events inside of tests?

Viewed 2596

I've just written a laravel Observer. It is attached to a Company model as I want to know the users that created a company. I have a large suite of other tests which use factories to setup companies. These tests now fail because the observer needs a user but no user is logged in when the factory is called.

CompanyObserver.php

class CompanyObserver {
    function created(Company $company) {
        info('USER ' . Auth::user()->id . ' created the new company ' . $company->id . '.';
    }
}

OldTests.php

Class OldTests {
    function testSomething() {
        // Now fails because observer is triggered but no use is logged in.
        $company = factory(Company::class)->create();

        // Random request
        $this->post('getCompany/' . $company->id)->assertStatus(200);
    }
}

How can I handle having a new observer that require a user to be logged in for my old tests? Do I have to go and change all my old tests?

2 Answers

In Laravel 8, this should work.

$company = Company::withoutEvents(function () {
        return Company::factory()->create();
    });

At the beginning of your test call Event::fake();

This will fake all the events in the test. You can the use asserting functions on the faked Event to complete your tests and see the events were fired.

You can fake the event for a specific scope like so

$company = Event::fakeFor(function () {
    $company = factory(Company::class)->create();

    Event::assertDispatched(CompanyCreated::class);

    return $company;
});
//use $company for the rest of the test

More info on faking the events in the documentation

Related