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

时间:2015-12-01 11:50:23

标签: php unit-testing phpunit mockery

在一个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

我很困惑,我期待模拟没有做任何事情但仍然允许调用方法,以便我以后可以添加我的期望。

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

1 个答案:

答案 0 :(得分:1)

模拟对象上存在shouldIgnoreMissing方法。调用exactly what it says on the tin,即:忽略对尚未定义的方法的调用,导致模拟无效:

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

没有任何东西,它没有任何意义。当我以这种方式实例化mock时,我的队列出现了另一个错误,因为默认情况下方法将返回null,并且必须明确声明它们的返回值。

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

getMessages的任何调用现在都会返回数组[$msg]

或者,通过添加shouldReceive,可以非常清楚地了解使用Mockery调用的方法:

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