3

我知道我做错了什么,因为这很奇怪,我从几天开始就在学习 PHPUnit。测试对象是receive()控制器动作:

class ReportController
{
    /**
     * @var \Symfony\Component\EventDispatcher\EventDispatcherInterface
     */
    private $dispatcher;

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

    /**
     * @param \Gremo\SkebbyBundle\Message\InboudSkebbyMessage $message
     * @return \Symfony\Component\HttpFoundation\Response
     */
    public function receive(InboudSkebbyMessage $message)
    {
        $this->dispatcher->dispatch(SkebbyEvents::MESSAGE_RECEIVED,
            new InboundMessageEvent($message)
        );

        return new Response();
    }
}

当控制器抛出一个事件时,我需要模拟一个事件订阅者(实现Symfony\Component\EventDispatcher\EventSubscriberInterface)。有一个静态方法getSubscribedEvents()。测试方法助手(获取模拟):

public function getMockSubscriber(array $events)
{
    $class = $this->getMockClass(
        'Symfony\Component\EventDispatcher\EventSubscriberInterface',
        array_merge(array_values($events), array('getSubscribedEvents'))
    );

    // Static stub method
    $class::staticExpects($this->once())
        ->method('getSubscribedEvents')
        ->will($this->returnValue($events))
    ;

    return new $class;
}

然后在我的测试方法中,我正在注册(模拟)订阅者,发出请求并检查是否onMessageReceived()被调用了一次。(实际上很大)问题是测试总是成功,即使我将模拟更改为$subscriber->expects($this->never())->method('onMessageReceived'). 执行:

public function testApiCall()
{
    $client = $this->createClient();

    // Router (for route generation) and dispatcher (for subscribing the mock)
    $router    = $client->getContainer()->get('router');
    $dispatcer = $client->getContainer()->get('event_dispatcher');

    // Get mock event subscriber
    $subscriber = $this->getMockSubscriber(array(
        'messsage.received' => 'onMessageReceived'
    ));

    // Register the mock subscriber with the dispatcher
    $subscriber->expects($this->once())->method('onMessageReceived');
    $dispatcer->addSubscriber($subscriber);

    // Make the request
    $request  = Request::create(
        $router->generate('controller_receive'),
        'POST',
        array(
            'sender'    => 'sender',
            'receiver'  => 'receiver',
            'text'      => 'text',
            'timestamp' => time(),
            'smsType'   => 'smsType'
        )
    );

    $client->getKernel()->handle($request);
}

编辑:模拟订户已在调度程序中正确注册。var_dump($dispatcher->getListeners())

array(7) {
  'messsage.received' =>
  array(1) {
    [0] =>
    array(2) {
      [0] =>
      class Mock_EventSubscriberInterface_19b191af#34 (2) {
        ...
      }
      [1] =>
      string(17) "onMessageReceived"
    }
  }
4

1 回答 1

3

我会使用模拟对象,而不是从类名创建一个新对象:

public function getMockSubscriber(array $events)
{
    $subscriberMock = $this->getMock(
        'Symfony\Component\EventDispatcher\EventSubscriberInterface',
        array_merge(array_values($events), array('getSubscribedEvents'))
    );

    // Static stub method
    $class = get_class(subscriberMock);
    $class::staticExpects($this->once())
        ->method('getSubscribedEvents')
        ->will($this->returnValue($events))
    ;

    return $subscriberMock;
}
于 2012-09-27T20:51:14.973 回答