19

我是单元测试和 PHPUnit 的新手。

我需要一个模拟,我有一个完全控制,实现ConfigurationInterface接口。测试主体是ReportEventParamConverter对象,测试必须检查我的对象与界面之间的交互。

ReportEventParamConverter对象(这里简化):

class ReportEventParamConverter implements ParamConverterInterface
{
    /**
     * @param Request $request
     * @param ConfigurationInterface $configuration
     */
    function apply(Request $request, ConfigurationInterface $configuration)
    {
        $request->attributes->set($configuration->getName(), $reportEvent);
    }

    /**
     * @param ConfigurationInterface $configuration
     * @return bool
     */
    function supports(ConfigurationInterface $configuration)
    {
        return 'My\Namespaced\Class' === $configuration->getClass();
    }
}

这就是我试图模拟界面的方式:

$cls = 'Sensio\Bundle\FrameworkExtraBundle\Configuration\ConfigurationInterface';
$mock = $this->getMock($mockCls);

我需要模拟两种方法的返回值:getClass()getName(). 例如:

$mock->expects($this->any())
    ->method('getClass')
    ->will($this->returnValue('Some\Other\Class'))
;

当我创建一个新的ReportEventParamConverter测试supports()方法时,我收到以下 PHPUnit 错误:

致命错误:调用未定义的方法 Mock_ConfigurationInterface_21e9dccf::getClass()。

$converter = new ReportEventParamConverter();
$this->assertFalse($converter->supports($mock));
4

3 回答 3

19

这是因为在 ConfigurationInterface 中没有声明“getClass”方法。此接口中的唯一声明是方法“getAliasName”。

您只需要告诉模拟您将使用哪些方法:

$cls = 'Sensio\Bundle\FrameworkExtraBundle\Configuration\ConfigurationInterface';
$mock = $this->getMock($cls, array('getClass', 'getAliasName'));

请注意,没有“getClass”声明,但您也可以存根/模拟不存在的方法。因此你可以模拟它:

$mock->expects($this->any())
    ->method('getClass')
    ->will($this->returnValue('Some\Other\Class'));

但此外,您需要模拟“getAliasName”方法,只要它是接口的方法或抽象方法,并且必须“实现”。例如。:

$mock->expects($this->any())
   ->method('getAliasName')
   ->will($this->returnValue('SomeValue'));
于 2012-09-26T11:06:33.240 回答
13

Cyprian 的回答帮助了我,但有一个问题需要注意。你可以模拟不存在的类,PHPUnit 不会抱怨。所以你可以做

$mock = $this->getMock('SomeClassThatDoesntExistOrIsMisspelledOrPerhapsYouForgotToRequire');

这意味着如果ConfigurationInterface在运行时该点不存在,您仍然会收到类似的消息

致命错误:调用未定义的方法 Mock_ConfigurationInterface_21e9dccf::getClass()。

如果您确定该方法确实存在于该类中,那么可能的问题是该类本身不存在(因为您不需要它,或者您拼写错误等)。


OP 正在使用interface。请注意,您必须getMock在不指定要覆盖的方法列表的情况下调用,或者如果这样做,则必须传递array()或传递所有方法名称,否则您将收到如下错误:

PHP 致命错误:Mock_HttpRequest_a7aa9ffd 类包含 4 个抽象方法,因此必须声明为抽象方法或实现其余方法(HttpRequest::setOption、HttpRequest::execute、HttpRequest::getInfo、...)

于 2014-05-04T08:08:33.523 回答
1

Tyler Collier 的警告是公平的,但不包含有关如何围绕它进行编码的代码片段。请注意,这非常讨厌,您应该修复界面。添加了该警告:

$methods = array_map(function (\ReflectionMethod $m) { return $m->getName();}, (new \ReflectionClass($interface))->getMethods());
$methods[] = $missing_method;
$mock = $this->getMock($interface,  $methods);
于 2015-04-01T16:23:24.003 回答