PHPUnit 模拟一个抽象类的所有方法
Posted
技术标签:
【中文标题】PHPUnit 模拟一个抽象类的所有方法【英文标题】:PHPUnit mock all methods of an abstract class 【发布时间】:2013-04-16 19:40:36 【问题描述】:我有一个直接从 phpUnit_Framework_TestCase 派生的 PHPUnit 测试用例。在此类的测试中,我需要为某些服务对象获取模拟。该服务对象是由抽象基类定义的类型。这个基类同时包含具体方法和抽象方法。我想得到一个完整的模拟(即所有方法都被模拟出来)。我的问题是如何做到这一点。
->getMock 给我一个错误,因为抽象方法没有被模拟,只有具体的方法
->getMockForAbstractClass 模拟出抽象方法,但不模拟出具体方法
我如何将它们全部模拟出来?
(我使用的是 PHPUnit 3.7.13)
【问题讨论】:
这已在此答案中提到的 PHPUnit 的更高版本中实现。 ***.com/a/13365088/498699 【参考方案1】:只需调用->getMock('Class');
即可模拟对象上的所有方法并实现所有抽象方法。
我不太确定你哪里出错了,但既然是这样,看起来很直接,我写了一个示例。
如果它不适合你,我需要一个重现你正在尝试做的事情的案例
示例
<?php
class mockTest extends PHPUnit_Framework_TestCase
// Without expectations
public function testMocking()
$x = $this->getMock('MockMe');
$this->assertNull($x->foo());
$this->assertNull($x->bar());
// With expectations
public function testMocking2()
$x = $this->getMock('MockMe');
$x->expects($this->once())->method('foo')->will($this->returnValue(true));
$x->expects($this->once())->method('bar')->will($this->returnValue(true));
$this->assertTrue($x->foo());
$this->assertTrue($x->bar());
abstract class MockMe
abstract public function foo();
public function bar()
return 1 + $this->foo();
生产
PHPUnit 3.7.13 by Sebastian Bergmann.
..
Time: 0 seconds, Memory: 6.25Mb
OK (2 tests, 5 assertions)
【讨论】:
我正在做 $this->getMock( 'SomeAbstractClass' )。得到这个:致命错误:类 Mock_SomeAbstractClass_cbc14c8a 包含 2 个抽象方法,因此必须声明为抽象方法或实现 /usr/share/php/PHPUnit/Framework/MockObject/Generator 中的剩余方法(SomeAbstractClass::foo,SomeAbstractClass::bar)。 php(231) : eval()'d 代码在第 3302 行 有趣的是,您的示例代码对我来说确实工作得很好。在我的例子中,抽象类非常复杂并且实现了一些接口。也许它在 PHPUnit 中引起了一些错误?我现在的解决方法是只在 getMock 方法调用中引用它的派生词之一。 当然总是可以的。或者它可能无法找到/加载其中一个接口并且无法事先找出方法(或其他东西!)。如果您可以使用可以共享错误报告的代码重现错误,那肯定会受到欢迎:)【参考方案2】:如果一个或多个抽象方法不是公共的,$this->getMock(...) 看起来对于抽象类将失败。
如果您不想使用派生类,可以在测试基类中添加类似这样的内容:
protected function getMockOfAbstractClass($originalClassName, $methods = array(), array $arguments = array(), $mockClassName = '', $callOriginalConstructor = TRUE, $callOriginalClone = TRUE, $callAutoload = TRUE)
if ($methods !== null)
$methods = array_unique(array_merge($methods,
$this->getMethods($originalClassName, $callAutoload)));
return parent::getMock($originalClassName, $methods, $arguments, $mockClassName, $callOriginalConstructor, $callOriginalClone, $callAutoload);
private function getMethods($class, $autoload=true)
$methods = array();
if (class_exists($class, $autoload) || interface_exists($class, $autoload))
$reflector = new ReflectionClass($class);
foreach ($reflector->getMethods( ReflectionMethod::IS_PUBLIC | ReflectionMethod::IS_ABSTRACT ) as $method)
$methods[] = $method->getName();
return $methods;
本文改编自:Mocking concrete method in abstract class using phpunit
【讨论】:
【参考方案3】:使用getMockForAbstractClass
,默认情况下不会模拟具体方法。要模拟具体方法,请使用第 7 个参数 ($mockedMethods
)。
【讨论】:
以上是关于PHPUnit 模拟一个抽象类的所有方法的主要内容,如果未能解决你的问题,请参考以下文章