Framework: Mailable->hasFrom doesn't work.

Created on 14 Jul 2017  Â·  7Comments  Â·  Source: laravel/framework

  • Laravel Version: 5.4.28
  • PHP Version: 7.0.18
  • Database Driver & Version: Mysql

Description:

I set the sender in my mailable class, and I want to write a simple test to make sure the mail is sent by the correct sender. However, the Mailable->hasFrom always return false. and I dump the $mail in my test, the from property is empty.

Steps To Reproduce:

<?php
// My mailable class
namespace App\Mail;

use Illuminate\Mail\Mailable;

class MyMail extends Mailable
{
    public function build()
    {
        return $this->from('[email protected]')
            ->text('test mail');
    }
}
<?php
// My Test class
namespace Tests\Unit;

use App\Mail\MyMail;
use Illuminate\Support\Facades\Mail;
use Tests\TestCase;

class MyMailTest extends TestCase
{
    /** @test */
    public function the_email_with_correct_sender()
    {
        Mail::fake();
        $myMail = new MyMail();
        Mail::to('[email protected]')
            ->send($myMail);
        Mail::assertSent(MyMail::class, function ($mail) {
            return $mail->hasFrom('[email protected]');
        });
    }
}

Most helpful comment

I did some testing it happens because of the build method not being triggered when you use MailFake if you use the following code it would work this is not a fix of course...

``` // My Test class
namespace Tests\Unit;

use App\Mail\MyMail;
use Illuminate\Support\Facades\Mail;
use TestsTestCase;

class MyMailTest extends TestCase
{
/** @test */
public function the_email_with_correct_sender()
{
Mail::fake();
$myMail = new MyMail();
Mail::to('[email protected]')
->send($myMail);
Mail::assertSent(MyMail::class, function ($mail) {
$mail->build(); // <-- add this
return $mail->hasFrom('[email protected]');
});
}
}
```

The code in the MailFake looks as follows

/**
 * Send a new message using a view.
 *
 * @param  string|array  $view
 * @param  array  $data
 * @param  \Closure|string  $callback
 * @return void
 */
public function send($view, array $data = [], $callback = null)
{
    if (! $view instanceof Mailable) {
        return;
    }

    $this->mailables[] = $view;
}

As you can see if you pass it a mailable it will just return and do nothing while the Mailable real method will call the build method.

All 7 comments

I'm running into what I think is the same issue. I post this about this a few days ago to. One of the contributors @themsaid just closed it because I had Laravel 5.3.31 installed and he said it wasn't supported and closed my thread. After that another developer posted that his wasn't working on 5.4 and I upgraded my framework to 5.4 and it still throws the exact same error.

I've also seen other threads about this, none of which were solved so I could get an answer. @taylorotwell

This is my post which shows the error I get.https://github.com/laravel/framework/issues/20059

I did some testing it happens because of the build method not being triggered when you use MailFake if you use the following code it would work this is not a fix of course...

``` // My Test class
namespace Tests\Unit;

use App\Mail\MyMail;
use Illuminate\Support\Facades\Mail;
use TestsTestCase;

class MyMailTest extends TestCase
{
/** @test */
public function the_email_with_correct_sender()
{
Mail::fake();
$myMail = new MyMail();
Mail::to('[email protected]')
->send($myMail);
Mail::assertSent(MyMail::class, function ($mail) {
$mail->build(); // <-- add this
return $mail->hasFrom('[email protected]');
});
}
}
```

The code in the MailFake looks as follows

/**
 * Send a new message using a view.
 *
 * @param  string|array  $view
 * @param  array  $data
 * @param  \Closure|string  $callback
 * @return void
 */
public function send($view, array $data = [], $callback = null)
{
    if (! $view instanceof Mailable) {
        return;
    }

    $this->mailables[] = $view;
}

As you can see if you pass it a mailable it will just return and do nothing while the Mailable real method will call the build method.

Thanks @Douglasdc3, my simple test pass after added $mail->build().

Hello @nivanmorgan has your problem been solved by @Douglasdc3's solution?

@wadleo The problem solved by @Douglasdc3 solution.

Ok cool

On Jul 24, 2017 3:05 AM, "Gump Lei" notifications@github.com wrote:

@wadleo https://github.com/wadleo The problem solved by @Douglasdc3
https://github.com/douglasdc3 solution.

—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/laravel/framework/issues/20056#issuecomment-317301794,
or mute the thread
https://github.com/notifications/unsubscribe-auth/AKfxRE88ebWTquEttR5hh7QZqfwhMkDNks5sQ_vzgaJpZM4OXv3R
.

Hi, I run into the same issue and @Douglasdc3's solution works.

But is there a good reason to not include this directly in the framework, in MailFake::send ?

/**
 * Send a new message using a view.
 *
 * @param  string|array  $view
 * @param  array  $data
 * @param  \Closure|string  $callback
 * @return void
 */
public function send($view, array $data = [], $callback = null)
{
    if (! $view instanceof Mailable) {
        return;
    }
    // Call build here fix the problem
    $this->mailables[] = $view->build();
}
Was this page helpful?
0 / 5 - 0 ratings