问题描述
有没有什么好的方法可以使用 PHPUnit 模拟抽象类中的具体方法?
Are there any good ways to mock concrete methods in abstract classes using PHPUnit?
到目前为止我发现的是:
- expects()->will() 使用抽象方法可以正常工作
- 它不适用于具体方法.而是运行原始方法.
- 使用 mockbuilder 并将所有抽象方法和具体方法提供给 setMethods() 有效.但是,它需要您指定所有抽象方法,这使得测试变得脆弱且过于冗长.
- MockBuilder::getMockForAbstractClass() 忽略 setMethod().
以下是一些对上述几点进行示例的单元测试:
Here are some unit tests examplifying the above points:
abstract class AbstractClass {
public function concreteMethod() {
return $this->abstractMethod();
}
public abstract function abstractMethod();
}
class AbstractClassTest extends PHPUnit_Framework_TestCase {
/**
* This works for abstract methods.
*/
public function testAbstractMethod() {
$stub = $this->getMockForAbstractClass('AbstractClass');
$stub->expects($this->any())
->method('abstractMethod')
->will($this->returnValue(2));
$this->assertSame(2, $stub->concreteMethod()); // Succeeds
}
/**
* Ideally, I would like this to work for concrete methods too.
*/
public function testConcreteMethod() {
$stub = $this->getMockForAbstractClass('AbstractClass');
$stub->expects($this->any())
->method('concreteMethod')
->will($this->returnValue(2));
$this->assertSame(2, $stub->concreteMethod()); // Fails, concreteMethod returns NULL
}
/**
* One way to mock the concrete method, is to use the mock builder,
* and set the methods to mock.
*
* The downside of doing it this way, is that all abstract methods
* must be specified in the setMethods() call. If you add a new abstract
* method, all your existing unit tests will fail.
*/
public function testConcreteMethod__mockBuilder_getMock() {
$stub = $this->getMockBuilder('AbstractClass')
->setMethods(array('concreteMethod', 'abstractMethod'))
->getMock();
$stub->expects($this->any())
->method('concreteMethod')
->will($this->returnValue(2));
$this->assertSame(2, $stub->concreteMethod()); // Succeeds
}
/**
* Similar to above, but using getMockForAbstractClass().
* Apparently, setMethods() is ignored by getMockForAbstractClass()
*/
public function testConcreteMethod__mockBuilder_getMockForAbstractClass() {
$stub = $this->getMockBuilder('AbstractClass')
->setMethods(array('concreteMethod'))
->getMockForAbstractClass();
$stub->expects($this->any())
->method('concreteMethod')
->will($this->returnValue(2));
$this->assertSame(2, $stub->concreteMethod()); // Fails, concreteMethod returns NULL
}
}
推荐答案
2年前有一个Pull Request,但从未在文档中添加信息:https://github.com/sebastianbergmann/phpunit-mock-objects/pull/49
There was a Pull Request for this 2 years ago, but the information never been added in the documentation : https://github.com/sebastianbergmann/phpunit-mock-objects/pull/49
您可以在 getMockForAbstractClass() 的参数 7 中的数组中传递具体方法.
You can pass your concrete method in an array in argument 7 of getMockForAbstractClass().
查看代码:https://github.com/andreaswolf/phpunit-mock-objects/blob/30ee7452caaa09c46421379861b4128ef7d95e2f/PHPUnit/Framework/MockObject/Generator.php#L225
这篇关于使用phpunit在抽象类中模拟具体方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!