首页 文章

PHP单元测试调度事件

提问于
浏览
1

如何在函数调用期间测试事件是否被调度?

public function updateUser() {
    //Do some update stuff

    $event = new UserUpdated($user);

    $event->attach([
        new SendEmailAddressChangeEmail($emailAddress),
        new SendEmailAddressChangeEmail($oldEmailAddress),
    ]);
    $event->dispatch();
}

除了设置电子邮件地址并查看是否发送了电子邮件之外,我如何检查(使用PHP单元)调度员实际上是否正在调度这些事件?我假设我需要创建某种类型的模拟,但我不确定如何为完全不相关的代码创建模拟 .

UserUpdated事件代码:

class UserUpdated extends BaseEvent
{

    public $user;

    public function __construct(User $user) {
        $this->user = $user;
    }
}

和相关的SendEmailAddressChanged处理程序代码:

class SendEmailAddressChangeEmail implements Contracts\HandlerInterface
{
    protected $emailAddress;

    public function __construct($emailAddress) {
        $this->emailAddress = $emailAddress;
    }

    public function handle($event) {
        EmailUtils::sendEmailAddressChangeEmail($this->emailAddress, $event->user->userName, $event->user->userID);
    }
}

1 回答

  • 1

    您获得的 updateUser() 方法在一个方面做了两件事,特别是对于(单元)测试不能很好地工作:

    • 业务逻辑

    • 对象创建

    从你自己的感觉来看,我认为这也是你问这个问题的原因 . 通常不直接测试的代码对于设计问题也是一个很好的金丝雀,因此通常最好解决它 .

    这两点(1.和2.)过分简化了Misko Hevery在他的清洁代码会谈中更详细地概述的“两桩”借来的内容:例如“清洁代码会谈” - 继承,多态性和测试“从2008年11月起 - https://youtu.be/4F72VULWFvc?t=1328("Two Piles”@ 22:08)

    使该代码更具可测试性的一种解决方案是使用依赖注入 . 这是用户事件的一个工厂(方法)和对象的一个工厂(方法) updateUser() 是一个方法 . 然后,该具体类型可以利用它注入的工厂对象来获得偶数对象 .

    简而言之:如果该更新用户对象需要用户更新事件对象,则需要在其构造函数中请求它 .

    由于您有时不希望事先创建该用户更新事件对象,另一种方法是注入一个知道如何创建该用户更新事件对象的对象,这些对象称为工厂 .

    然后,测试可以注入一个工厂,该工厂提供一个事件模拟对象,期望它被调度 .

    一个很好的调度库btw . 已经为测试提供了现成的模拟,但这超出了Phpunit的范围 .

    如果您还不知道Phpunit的模拟功能,请查看产品的文档:

相关问题