如何测试在函数调用期间调度事件?
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);
}
}
答案 0 :(得分:1)
你所获得的updateUser()
方法在一个方面做了两件事情,尤其是(单位)测试效果不佳:
从你自己的感觉来看,我认为这也是你问这个问题的原因。通常不直接测试的代码对于设计问题来说也是一个好的金丝雀,因此通常最好用它来解决。
这两点(1.和2.)是过度简化从"两桩" Misko Hevery在他的清洁代码会谈中详细介绍了
例如" The Clean Code Talks - Inheritance,Polymorphism,&测试"从2008年11月起 - https://youtu.be/4F72VULWFvc?t=1328(" Two Piles" @ 22:08)
使这段代码更具可测试性的一个解决方案是使用依赖注入。这是用户事件的一个工厂(方法),而对象updateUser()
的一个工厂(方法)是一个方法。然后,该具体类型可以使用它注入的工厂对象来获得偶数对象。
简而言之:如果该更新用户对象需要用户更新事件对象,则需要在其构造函数中请求它。
由于您有时不想事先创建该用户更新事件对象,另一种方法是注入一个知道如何创建该用户更新事件对象的对象,这些对象称为工厂
然后,测试可以注入一个工厂,该工厂提供一个事件模拟对象,期望它被调度。
一个好的调度库btw。已经为测试提供了现成的模拟,但这超出了Phpunit的范围。
如果您还不了解Phpunit的模拟功能,请查看产品的文档: