Skip to content

[5.5] Mail::assertQueued() callback is missing mailable data #20700

@lbausch

Description

@lbausch
  • Laravel Version: 5.5 @ 3c888b6
  • PHP Version: 7.1.7-1+ubuntu16.04.1+deb.sury.org+1
  • Database Driver & Version: PDO with MySQL 5.7.19-0ubuntu0.16.04.1

Description:

I'm queuing a mailable (AuthTokenMail) with the following code where $token is a model:

use Illuminate\Support\Facades\Mail;
Mail::to($token->user->email)->queue(new AuthTokenMail($token));

While the mail is being sent in production, my test fails:

There was 1 failure:

1) Tests\Feature\AuthTest::testAuthTokenIsSent
The expected [App\Mail\AuthTokenMail] mailable was not queued.
Failed asserting that false is true.

/home/vagrant/Code/vendor/laravel/framework/src/Illuminate/Support/Testing/Fakes/MailFake.php:100
/home/vagrant/Code/vendor/laravel/framework/src/Illuminate/Support/Facades/Facade.php:221
/home/vagrant/Code/tests/Feature/AuthTest.php:28
use Illuminate\Support\Facades\Mail;
public function testAuthTokenIsSent()
{
        Mail::fake();

        $user = factory(User::class)->create();

        $response = $this->get('/auth');

        $response->assertSeeText('Mail queued');

        Mail::assertQueued(AuthTokenMail::class, function ($mail) use ($user) {
            return $mail->hasTo($user->email) && isset($mail->authToken);
        });
}

When I dd() the $mail variable inside the callback it has the authToken property populated - but all other data are empty. Especially to is an empty array which makes the hasTo() method return false and the test ultimately fail.

This test worked fine when I was using assertSent before the PR #20454
After the PR even assertSent does not work anymore.

Steps To Reproduce:

  1. Create a Mailable:
<?php

namespace App\Mail;

use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
use App\AuthToken;

class AuthTokenMail extends Mailable
{
    use Queueable, SerializesModels;

    /**
     * Auth token.
     *
     * @var AuthToken
     */
    public $authToken;

    /**
     * Create a new message instance.
     *
     * @param AuthToken $authToken
     */
    public function __construct(AuthToken $authToken)
    {
        $this->authToken = $authToken;
    }

    /**
     * Build the message.
     *
     * @return $this
     */
    public function build()
    {
        $text = action('AuthController@authWithToken', $this->authToken->token);

        return $this->view('emails.plain', [
            'text' => $text,
        ])->subject('AuthToken');
    }
}
  1. Create a controller method which queues the mailable
  2. Create a test which hits the controller route / method which queues the mail
  3. Use Mail::assertQueued and a callback with hasTo() to verify the receiver of the mail

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions