如何在Laravel 4中测试Mail Facade

8

我似乎不能让邮件门面接受一个 ->with() 命令进行测试。

这是有效的:

Mail::shouldReceive('send')->once();

但是这个并不起作用:
Mail::shouldReceive('send')->with('emails.welcome')->once();

而这个也不行:
Mail::shouldReceive('send')->with('emails.welcome', array(), function(){})->once();

这个也不行:

Mail::shouldReceive('send')->with('emails.welcome', array(), function($message){})->once();

所有的都会给出以下错误:

"No matching handler found for Illuminate\Mail\Mailer::send("emails.welcome", Array, Closure)"

那么我如何测试邮件以检查它接收到了什么?

另外 - 对于额外的加分 - 是否有可能测试邮件在闭包内部执行的内容?也就是说,我可以检查$message->to()设置为什么吗?

编辑:我的邮件代码:

Mail::send("emails.welcome", $data, function($message)
{
    $message->to($data['email'], $data['name'])->subject('Welcome!');
});
1个回答

25

以下代码示例假定使用 PHP 5.4 或更高版本 - 如果您使用的是 5.3 版本,则需要在下面的代码之前添加 $self = $this,并在第一个闭包中使用 use ($self),并将闭包内所有对 $this 的引用替换为 $self

模拟 SwiftMailer

最简单的方法是模拟 Swift_Mailer 实例。您需要了解 Swift_Message 类中存在哪些方法,以充分利用它。

$mock = Mockery::mock('Swift_Mailer');
$this->app['mailer']->setSwiftMailer($mock);
$mock->shouldReceive('send')->once()
    ->andReturnUsing(function(\Swift_Message $msg) {
        $this->assertEquals('My subject', $msg->getSubject());
        $this->assertEquals('foo@bar.com', $msg->getTo());
        $this->assertContains('Some string', $msg->getBody());
    });

关于闭包的断言

另一种解决方法是对传递给Mail::send的闭包运行断言。这看起来并不十分简洁,错误信息也可能相当难以理解,但它确实可行且非常灵活,并且该技术也可以用于其他事情。

use Mockery as m;

Mail::shouldReceive('send')->once()
    ->with('view.name', m::on(function($data) {
        $this->assertContains('my variable', $data);
        return true;
    }), m::on(function($closure) {
        $message = m::mock('Illuminate\Mailer\Message');
        $message->shouldReceive('to')
            ->with('test@example.com')
            ->andReturn(m::self());
        $message->shouldReceive('subject')
            ->with('Email subject')
            ->andReturn(m::self());
        $closure($message);
        return true;
    }));

在这个例子中,我正在对传递给视图的数据运行断言,如果收件人地址、主题或视图名称不正确,Mockery 将返回错误。

Mockery::on() 允许您在被模拟方法的参数上运行一个闭包。如果它返回 false,则会得到 "No matching handler found",但我们想要执行断言,所以我们返回 true。Mockery::self() 允许方法链接调用。

如果您不关心方法调用的某个参数是什么,可以使用 Mockery::any() 来告诉 Mockery 它接受任何参数。


Andreas,你的回答太好了!我希望我能点赞十几次!!:-) 谢谢! - casafred
在L5中应该是m::mock('Illuminate\Mail\Message'),否则不需要任何更改就可以工作! - MightyPork

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接