2013-08-23 50 views
2

使用PHPUnit进行测试,我的测试在函数上失败。但我不知道为什么。 的功能,我想嘲笑:Mockery Exception NoMatchingExpectationException 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 protected]'; 
    $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()方法,它似乎对您的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 protected]'; 
    $this->Mock(
     ->shouldReceive('setEmailAddress') 
     ->once() 
     ->will_return($email) 
     ); 

    $SubscribeMessage = new SubscribeMessage($this->Mock); 
    $SetEmail = $SubscribeMessage->setEmailAddress($email); 
    $this->assertEquals($email, $SetEmail); 
} 
相关问题