Я работаю над проектом, используя Laravel. Я хочу использовать события и уведомления. Для контекста: организация может опубликовать задачу (можно сравнить с вакансией). Пользователь может подать заявку на эту работу. Как только Пользователь подает заявку на Задание, электронное письмо должно быть отправлено на контактный адрес электронной почты, сохраненный вместе с Заданием.
Мое событие: ApplicationCreated Мое уведомление: ApplicationCreatedNotification Мой слушатель: SendApplicationCreatedNotification
Моя функция контроллера:
public function store(StoreApplicationRequest $request, Task $task)
{
Gate::authorize('store', [Application::class, $task]);
$application = null;
DB::transaction(function () use ($request, $task, &$application) {
$application = $task->applications()->create([
...$request->validated(),
'user_id' => auth()->id(),
]);
$application->load('user');
$application->setRelation('task', $task);
});
ApplicationCreated::dispatch($application);
return response()->json($application, 201);
}
Моя функция дескриптора в прослушивателе:
public function handle(ApplicationCreated $event): void
{
$recipient = $event->application->task->contact_email;
$name = $event->application->task->contact_firstname . ' ' . $event->application->task->contact_lastname;
Notification::route('mail', [
$recipient => $name,
])
->notify(new ApplicationCreatedNotification($event->application));
// @TODO: Send notification to the applicant as well
// something like this:
// "You successfully applied to the task: $task->title"
}
И мой тест:
public function test_user_can_apply_to_task(): void
{
$user = User::factory()->organization()->create();
$orga = Organization::factory()->forUser($user)->create();
$task = Task::factory()->forOrganization($orga)->create();
$basicUser = User::factory()->create();
Event::fake();
Notification::fake();
$response = $this->actingAs($basicUser)->post(route('applications.store', $task->id));
Event::assertDispatched(ApplicationCreated::class);
Notification::assertSentOnDemand(ApplicationCreatedNotification::class, function (ApplicationCreatedNotification $notification, array $channels, object $notifiable) use ($task) {
$recipient = $task->contact_email;
$name = $task->contact_firstname . ' ' . $task->contact_lastname;
return $notifiable->routes['mail'] === [$recipient => $name];
});
$response->assertStatus(201);
$this->assertDatabaseHas('applications', [
'task_id' => $task->id,
'user_id' => $basicUser->id,
]);
}
Я получаю этот вывод:
FAILED Tests\Feature\CreateApplicationTest > user can apply to task
The expected [App\Notifications\ApplicationCreatedNotification] notification was not sent.
Failed asserting that false is true.
at vendor\laravel\framework\src\Illuminate\Support\Testing\Fakes\NotificationFake.php:89
85▕ if (is_numeric($callback)) {
86▕ return $this->assertSentToTimes($notifiable, $notification, $callback);
87▕ }
88▕
➜ 89▕ PHPUnit::assertTrue(
90▕ $this->sent($notifiable, $notification, $callback)->count() > 0,
91▕ "The expected [{$notification}] notification was not sent."
92▕ );
93▕ }
1 vendor\laravel\framework\src\Illuminate\Support\Testing\Fakes\NotificationFake.php:89
2 vendor\laravel\framework\src\Illuminate\Support\Testing\Fakes\NotificationFake.php:54
Я знаю, что вызывается функция handle, потому что, когда я добавляю dd($recipient, $name); exit(0);, процесс тестирования останавливается, и я получаю этот вывод
"[email protected]" // app\Listeners\SendApplicationCreatedNotification.php:33
"Katrin Thomas" // app\Listeners\SendApplicationCreatedNotification.php:33
После некоторой отладки я обнаружил, что при выполнении моего теста запускается событие NotificationSent. Это событие отправляется классом NotificationSender:
protected function sendToNotifiable($notifiable, $id, $notification, $channel)
{
if (! $notification->id) {
$notification->id = $id;
}
if (! $this->shouldSendNotification($notifiable, $notification, $channel)) {
return;
}
$response = $this->manager->driver($channel)->send($notifiable, $notification);
$this->events->dispatch(
new NotificationSent($notifiable, $notification, $channel, $response)
);
}
Все поддельные уведомления «отправляются» классом NotificationFake, который реализует NotificationDispatcher, который является псевдонимом интерфейса Dispatch.
Похоже, что при отправке уведомления onDemand он не использует класс NotificationFake в качестве своего диспетчера.
Есть ли у кого-нибудь идеи, почему это не работает?
Если вы добавляете dd (в следующий раз добавьте dump), и он запускается, тогда dump($notifiable->routes['mail'] === [$recipient => $name]) и посмотрите, true или false это, и продолжите базовую отладку.
@krisgjika нет, я не уверен, но этот код даже не выполняется, так как приложение почему-то не отправляется.
@matiaslauriti код, на который вы ссылаетесь, находится внутри функции обратного вызова, которая не выполняется. Потому что уведомление не отправляется. Я проверил это с помощью dump и exit(), выходных данных нет, и код не запускается.






Прочитав документацию, я обнаружил, что вызов Event::fake() предотвратит запуск прослушивателя событий. Поэтому уведомления не будут отправлены. Итак, удаление Event::fake() решает мою проблему.
вы уверены, что эта проверка
$notifiable->routes['mail'] === [$recipient => $name]верна? Что такое$notifiable->routes['mail']?