如何修复抛出 BadMethodCallException 的嘲弄模拟对象?

How to fix mockery mock object throwing BadMethodCallException?

在 silex 应用程序中我有一个 KafkaAPiClient class 肯定有 public 方法 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,但是在测试中模拟 class 时:

<?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

我很困惑,我原以为模拟不会做任何事情,但允许调用方法,以便我以后可以在上面添加我的期望。

虽然我找到了解决办法,但我仍然想知道是否可以默认模拟所有方法,然后再检查是否调用了某些方法。

模拟对象上存在 shouldIgnoreMissing 方法。调用确实 exactly what it says on the tin,即:忽略对尚未定义的方法的调用,导致模拟不执行任何操作:

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

毫无意义,毫无意义。当我以这种方式实例化模拟时,我的队列遇到了另一个错误,因为默认情况下方法将 return null 并且必须明确说明它们的 return 值。

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

任何对 getMessages 的调用现在都会 return 恰好是数组 [$msg]

或者,可以通过添加 shouldReceive:

来非常明确地说明用 Mockery 调用了哪些方法
public function testMockMethodIsCallable()
{
    $leMock = \Mockery::mock(KafkaApiClient::class);
    $leMock->shouldReceive('postMessages');
    $leMock->postMessages([]);
}