Can you show the code for sending the email?
Is Mail:fake() and asserts really working ?
Hello,
I'm trying to test email sendings with the native officiel faker Mail::fake() but I can't have it work.
My email is a classical Mailable which is not queued :
class UserAlsoCommentedMail extends Mailable
{
use SendinBlue;
public function __construct(private UserAlsoCommentedNotification $notification)
{
// Do some stuff....
}
public function build()
{
$subject = "My subject";
return $this
->subject($subject)
->view(
'mail.user-also-commented',
)
->text(
'mail.user-also-commented-text',
)
->sendinblue(
[
'tags' => [
'tag1',
'tag2',
],
]
);
}
}
My test :
public function testPostCreateEvent()
{
Mail::fake();
//Given
$userOwner = User::factory()->createOne();
$userComment = User::factory()->createOne();
/** @var Publication $publication */
$publication = Publication::factory()->createOne([
'user_id'=> $userOwner->id
]);
//When
$response = $this
->actingAs($userComment, 'user')
->json('POST', "/api/v1/my-endpoint/comments", [
'description' => 'a new comment',
]);
//Then
$response->assertSuccessful();
$publication->refresh();
Mail::assertSent(CommentCreatedMail::class);
Mail::assertSent(UserAlsoCommentedMail::class);
}
My emails are instanciated and built, so is the MailFake but the Mail::assertSent are always false.
Digging into Laravel, I landed onto MailFake::send function which returns too early in my case :
/**
* Send a new message using a view.
*
* @param \Illuminate\Contracts\Mail\Mailable|string|array $view
* @param array $data
* @param \Closure|string|null $callback
* @return void
*/
public function send($view, array $data = [], $callback = null)
{
if (! $view instanceof Mailable) {
return; // I return here as my views are just array and not Mailable
}
$view->mailer($this->currentMailer);
$this->currentMailer = null;
if ($view instanceof ShouldQueue) {
return $this->queue($view, $data);
}
$this->mailables[] = $view;
}
In my case, I return from the first condition as my views are just array and not Mailable.
I think there is someting wrong here in Laravel MailFake as email views cannot be Mailable but arrays of Blade views.
What do you think about that ? Do your Mail::assertSent work ?
Hello,
at last, I went through that problem by stopping at the notification level as the Mail::fake() seems to be made for "facade" sent emails and not "notifications" sent emails.
Stopping at notification level, you then have to prepare the email by yourself :
public function testSendValidNotification()
{
Notification::fake();
//Given
...
///When
...
//Then
Notification::assertSentTo(
$user,
ValidNotification::class,
function (ValidNotification $n, $channels) use ($content, $user) {
$mail = $n->toMail($user)->build();
$mail->assertSeeInHtml("Validated !");
$mail->assertSeeInText("Validated !");
return
in_array('mail', $channels) &&
$n->content->is($content) &&
$mail->hasTo($user->email) &&
$n->notifiable->id === $user->id;
}
);
}
Illuminate\Mail\Mailable class gives you some useful assert functions :
public function assertSeeInHtml($string)
public function assertDontSeeInHtml($string)
public function assertSeeInText($string)
public function assertDontSeeInText($string)
Please or to participate in this conversation.