有没有一种方法可以在Laravel 5中测试Mail?尝试了我在互联网上看到的唯一合法的Mock示例,但似乎仅适用于Laravel4。下面是当前代码。

    $mock = Mockery::mock('Swift_Mailer');
    $this->app['mailer']->setSwiftMailer($mock);

    ...some more codes here...

    $mock->shouldReceive('send')->once()
         ->andReturnUsing(function($msg) {
             $this->assertEquals('My subject', $msg->getSubject());
             $this->assertEquals('foo@bar.com', $msg->getTo());
             $this->assertContains('Some string', $msg->getBody());
         });

这是ApiClient.php的内容,最后一行是第155行,该行在堆栈跟踪中指示。
Mail::queue('emails.error', [
                    'error_message' => $error_message,
                    'request' => $request,
                    'stack_trace' => $stack_trace
                ], function ($message) use ($error_message) {
                    $message->to(env('MAIL_TO_EMAIL'), env('MAIL_TO_NAME'))->subject("[Project Error] " . $error_message);
                });

下面是堆栈跟踪
Method Mockery_0__vendor_Swift_Mailer::getTransport() does not exist on this mock object
 /Users/BON/WebServer/project/vendor/laravel/framework/src/Illuminate/Mail/Mailer.php:285
 /Users/BON/WebServer/project/vendor/laravel/framework/src/Illuminate/Mail/Mailer.php:285
 /Users/BON/WebServer/project/vendor/laravel/framework/src/Illuminate/Mail/Mailer.php:150
 /Users/BON/WebServer/project/vendor/laravel/framework/src/Illuminate/Mail/Mailer.php:255
 /Users/BON/WebServer/project/vendor/laravel/framework/src/Illuminate/Queue/Jobs/Job.php:126
 /Users/BON/WebServer/project/vendor/laravel/framework/src/Illuminate/Queue/Jobs/SyncJob.php:42
 /Users/BON/WebServer/project/vendor/laravel/framework/src/Illuminate/Queue/SyncQueue.php:25
 /Users/BON/WebServer/project/vendor/laravel/framework/src/Illuminate/Mail/Mailer.php:184
 /Users/BON/WebServer/project/vendor/laravel/framework/src/Illuminate/Support/Facades/Facade.php:216
 /Users/BON/WebServer/project/app/Libraries/ApiClient.php:155
 /Users/BON/WebServer/project/app/Libraries/ApiClient.php:155
 /Users/BON/WebServer/project/app/Libraries/ApiClient.php:174
 /Users/BON/WebServer/project/tests/unit_tests/ApiClientUnitTest.php:43

此外,添加use Mockery;会出现以下错误。
PHP Warning:  The use statement with non-compound name 'Mockery' has no effect in /Users/BON/WebServer/project/tests/unit_tests/ApiClientUnitTest.php on line 9

这使我沮丧了好几个小时,以至于我已经在这里提出了这样的要求。奇怪的是,当Laravel决定升级到版本5时,在进行单元测试时没有直接支持测试邮件。

最佳答案

花了我一个下午的大部分时间,但这终于奏效了-我通过了一个Closure,并给了它一个Mockery对象

正在测试的代码:

$subject = "The subject";

Mail::send('emails.emailTemplate', ['user' => $user ],
function( $mail ) use ($user, $subject){
    $mail   -> to( $user -> email)
            -> subject( $subject );
});

测试有效:
$subject = "The subject";
$user = factory(App\Models\User::class) -> create();

Mail::shouldReceive('send') -> once() -> with(
        'emails.emailTemplate',
        m::on( function( $data ){
            $this -> assertArrayHasKey( 'user', $data );
            return true;
        }),
        m::on( function(\Closure $closure) use ($user, $subject){
            $mock = m::mock('Illuminate\Mailer\Message');
            $mock -> shouldReceive('to') -> once() -> with( $user -> email )
                  -> andReturn( $mock ); //simulate the chaining
            $mock -> shouldReceive('subject') -> once() -> with($subject);
            $closure($mock);
            return true;
        })
    );

10-07 18:54
查看更多