Как исправить насмешливый фиктивный объект, вызывающий исключение BadMethodCallException?

В приложении silex у меня есть класс KafkaAPiClient, который определенно имеет общедоступный метод postMessages.

<?php

namespace Kopernikus\KafkaWriter;

use Kopernikus\KafkaWriter\Model\AbstractMessage;

/**
 * KafkaApiClient.
 **/
class KafkaApiClient
{

    /**
     * @param AbstractMessage[] $msg
     */
    public function postMessages(array $messages)
    {
        foreach ($messages as $message) {
            $this->postMessage($message);
        }
    }

    public function postMessage(AbstractMessage $msg)
    {
         ...
    }
}

Я могу просто вызвать KafkaAPiClient::postMessages, но при издевательстве над классом в тесте:

<?php
namespace unit\Request;

use Kopernikus\KafkaWriter\KafkaApiClient;

/**
 * MockeryMethodsNotBeingCallableTest
 **/
class MockeryMethodsNotBeingCallableTest extends \PHPUnit_Framework_TestCase
{
    public function testMockMethodIsCallable()
    {
        $leMock = \Mockery::mock(KafkaApiClient::class);
        $leMock->postMessages([]);
    }
}

Я получаю:

1) unit\Request\MockeryMethodsNotBeingCallableTest::testMockMethodIsCallable
BadMethodCallException: Method Mockery_11_Kopernikus_KafkaWriter_KafkaApiClient::postMessages() does not exist on this mock object

~/le-project/tests/unit/Request/MockeryMethodsNotBeingCallableTest.php:14

Я в замешательстве, я ожидал, что макет ничего не сделает, но позволит вызывать методы, чтобы позже я мог добавить к нему свои ожидания.

Хотя я нашел решение, мне все еще интересно, можно ли смоделировать все методы по умолчанию, а затем проверить, были ли вызваны определенные из них.


person k0pernikus    schedule 01.12.2015    source источник
comment
он говорит, что у него нет функции postMessages ()? я думаю, вы должны проверить KafkaApiClient   -  person Murat Cem YALIN    schedule 01.12.2015
comment
@MuratCemYALIN Нет, у конкретного класса есть метод. Я был абсолютно уверен в этом, это макет, который не делает.   -  person k0pernikus    schedule 01.12.2015
comment
может он защищенный или частный?   -  person Murat Cem YALIN    schedule 01.12.2015
comment
@MuratCemYALIN Это общедоступно, и это не проблема. Конкретный класс НЕ является проблемой.   -  person k0pernikus    schedule 01.12.2015


Ответы (1)


В фиктивном объекте существует метод shouldIgnoreMissing. Вызов, который делает в точности то, что написано на банке, а именно: игнорирует вызовы еще не определенные методы, что приводит к макету, который ничего не делает:

$leMock = \Mockery::mock(KafkaApiClient::class);
$leMock->shouldIgnoreMissing()
$leMock->postMessages([]);

И ничего, это ничего не значит. Я столкнулся с другой ошибкой для своей очереди, когда я создал экземпляр макета таким образом, поскольку методы будут возвращать null по умолчанию, и их возвращаемое значение должно быть указано явно.

$msg = new Message('dummy-message');
$this->kafkaQueue
     ->shouldIgnoreMissing()
     ->shouldReceive('getMessages')->andReturn([$msg]);

Любой вызов getMessages теперь будет возвращать именно массив [$msg].

В качестве альтернативы можно очень явно указать, какие методы вызываются с помощью Mockery, добавив shouldReceive:

public function testMockMethodIsCallable()
{
    $leMock = \Mockery::mock(KafkaApiClient::class);
    $leMock->shouldReceive('postMessages');
    $leMock->postMessages([]);
}
person k0pernikus    schedule 01.12.2015