To test an event subscriber in Laravel, you need to ensure that the event is dispatched and the subscriber's method is called correctly. Here's a step-by-step guide to achieve this:
-
Mock the event and the subscriber: Use Laravel's
Event::fake()to fake the event and then assert that the event was dispatched. - Mock the method in the subscriber: Use PHPUnit's mocking capabilities to ensure that the subscriber's method is called when the event is dispatched.
Here's how you can structure your test:
Step 1: Test Event Dispatching
This part of your test is already correct. You are ensuring that the event is dispatched when the action is performed.
public function test_application_approve_for_interview_event_dispatched()
{
Event::fake([
ApplicationWasApprovedForInterview::class
]);
$application = ApplicationTestFactory::createApplication();
$this->assertTrue($application->acceptedStatus === 'Pending');
$action = new ApproveForInterview();
$action->handle(new ActionFields(collect([]), collect()), collect([$application]));
$this->assertNotNull($application->approved_for_interview_at);
// Assert that an event was dispatched...
Event::assertDispatched(ApplicationWasApprovedForInterview::class);
}
Step 2: Test Event Subscriber
To test the subscriber, you need to mock the method that should be called when the event is dispatched. Here's how you can do it:
public function test_application_approve_for_interview_event_listener()
{
Event::fake();
$application = ApplicationTestFactory::createApplication();
$application->approved_for_interview_at = null;
// Mock the subscriber
$subscriber = $this->getMockBuilder(ApplicationEventSubscriber::class)
->onlyMethods(['notifyWhenApplicationWasApprovedForInterview'])
->getMock();
// Expect the method to be called once
$subscriber->expects($this->once())
->method('notifyWhenApplicationWasApprovedForInterview')
->with($this->isInstanceOf(ApplicationWasApprovedForInterview::class));
// Register the mock subscriber
$this->app->instance(ApplicationEventSubscriber::class, $subscriber);
// Dispatch the event
event(new ApplicationWasApprovedForInterview($application, true));
// Assert that the event was dispatched
Event::assertDispatched(ApplicationWasApprovedForInterview::class);
}
Explanation:
-
Mock the Subscriber: We create a mock of the
ApplicationEventSubscriberclass and specify that we only want to mock thenotifyWhenApplicationWasApprovedForInterviewmethod. -
Set Expectations: We set an expectation that the
notifyWhenApplicationWasApprovedForInterviewmethod should be called exactly once with an instance ofApplicationWasApprovedForInterview. -
Register the Mock: We register the mock subscriber in the service container using
$this->app->instance(). -
Dispatch the Event: We dispatch the event and then assert that the event was dispatched using
Event::assertDispatched().
This approach ensures that your event subscriber is correctly listening to the event and that the appropriate method is called when the event is dispatched.