我正在使用PHPUnit进行测试,我的测试在函数上失败了。但我不知道为什么。 我想要模拟的功能:
public function subscribe($email)
{
$message = new SubscribeMessage();
$message->setEmailaddress($email);
$message->setLocale(Locale::getDefault());
$this->getAmqpProducer()->publish($message, 'newsletter-subscribe');
return true;
}
和我的单元测试:
public function testSubscribeSendsAmqpMessage()
{
$email = 'email@email.nl';
$locale = 'nl';
$this->amqpProducerMock
->shouldReceive('publish')
->once()
->with(
\Mockery::on(
function ($message, $routingkey) use (&$publishedMessage) {
$publishedMessage = $message;
return $routingkey == 'newsletter-subscribe';
}
)
);
$this->service->subscribe($email, $locale);
}
但测试说:
Mockery\Exception\NoMatchingExpectationException : No matching handler found for AcsiRabbitMq\Producer\Producer::publish(AcsiNewsletter\RabbitMq\Message\SubscribeMessage, "newsletter-subscribe"). Either the method was unexpected or its arguments matched no expected argument list for this method
如何修复单元测试?或者我如何重构我的测试?
答案 0 :(得分:1)
你嘲笑订阅,而不是内部发布。当您运行测试并调用 - > subscribe时,它将尝试执行该类中的代码。因此,它会尝试运行subscribe()方法,你似乎对你的Mock有一个奇怪的引用。
通常,您的测试将模拟订阅,因此您可以返回断言测试的值,该测试是硬编码的。
您似乎试图模拟常规代码中的GetAmqpProducer()对象。您需要能够将模拟对象传递给您的类,或者能够分配它。
简化示例:
class Email
{
private $MsgObject;
// Constructor Injection
public __construct(SubscribeMessage $MessageObject)
{
$this->MsgObject = $MessageObject;
...
}
// Setter Injection
public function SetSubscribeMessage(Subscribe $MessageObject)
{
$this->MsgObject = $MessageObject;
}
public function setEmailaddress($email)
{
$this->MsgObject->emailAddress = $email;
...
}
public function setLocale($Locale)
{
$this->MsgObject->Locale = $Locale;
...
}
...
}
上面的类示例有太多的内部对象和依赖项需要进行测试,因为测试实际上会调用它们。您可以使用依赖注入来传递具有已知状态的对象,并让它们正确返回。
请注意,我没有在Mockery中展示如何做到这一点,因为我没有使用它,但是这个简单的例子可以帮助你理解我想要表达的内容。
所以一个简单的测试可能看起来像:
public function testSubscribeMessage()
{
$email = 'email@email.nl';
$this->Mock(
->shouldReceive('setEmailAddress')
->once()
->will_return($email)
);
$SubscribeMessage = new SubscribeMessage($this->Mock);
$SetEmail = $SubscribeMessage->setEmailAddress($email);
$this->assertEquals($email, $SetEmail);
}