Mails
Don't actually send emails in tests
Use Mail::fake() to assert emails are queued without sending them.
Mailable
// app/Mail/OrderConfirmation.php
class OrderConfirmation extends Mailable
{
public function __construct(public Order $order) {}
public function envelope(): Envelope
{
return new Envelope(
from: new Address('[email protected]', 'Example Shop'),
subject: "Order #{$this->order->id} Confirmed",
);
}
public function content(): Content
{
return new Content(
markdown: 'emails.order-confirmation',
with: [
'trackingUrl' => "https://example.com/track/{$this->order->tracking_number}",
],
);
}
}
Controller
// app/Http/Controllers/OrderController.php
public function store(StoreOrderRequest $request)
{
$order = Order::create($request->validated());
Mail::to($order->email)
->send(new OrderConfirmation($order));
// ...
}
Feature Test — assert mail is sent
// tests/Feature/Http/Controllers/OrderController/StoreTest.php
Mail::fake();
$this->post(route('orders.store'), $data);
Mail::assertOutgoingCount(1);
Mail::assertQueued(OrderConfirmation::class, function ($mail) {
$this->assertTrue($mail->hasTo('[email protected]'));
$this->assertSame('Order #1 Confirmed', $mail->subject);
return true;
});
Unit Test — assert mail content
// tests/Unit/Mail/OrderConfirmationTest.php
class OrderConfirmationTest extends TestCase
{
#[Test]
public function mail_has_correct_subject(): void
{
$order = Order::factory()->create();
$mail = new OrderConfirmation($order);
$this->assertSame(
"Order #{$order->id} Confirmed",
$mail->envelope()->subject
);
}
#[Test]
public function mail_has_correct_recipient(): void
{
$order = Order::factory()->create([
'email' => '[email protected]',
]);
$mail = new OrderConfirmation($order);
$this->assertTrue($mail->hasTo('[email protected]'));
}
#[Test]
public function mail_has_tracking_url_in_data(): void
{
$order = Order::factory()->create([
'tracking_number' => 'TRACK123',
]);
$mail = new OrderConfirmation($order);
$this->assertArrayHasKey('trackingUrl', $mail->content()->with);
$this->assertStringContainsString(
'TRACK123',
$mail->content()->with['trackingUrl']
);
}
}