Phpunit,如何模拟抽象类?
我说的是这个功能:Phpunit,如何模拟抽象类?,php,unit-testing,mocking,phpunit,Php,Unit Testing,Mocking,Phpunit,我说的是这个功能: function testMeSomehow ($id, Flag $flags) { $flags::NAME; } 其参数对象: abstract class Flag { abstract function method1(); abstract function method2(); . . . abstract function method999(); } 如何模拟这个标志类?它有很多抽象的方法,我应该用空的主体来创建它们吗?如
function testMeSomehow ($id, Flag $flags)
{
$flags::NAME;
}
其参数对象:
abstract class Flag
{
abstract function method1();
abstract function method2();
.
.
.
abstract function method999();
}
如何模拟这个
标志
类?它有很多抽象的方法,我应该用空的主体来创建它们吗?如果这个类发生变化呢?我还必须向它添加一个名称
常量您可以像对任何其他类一样,使用测试加倍来模拟它,请参见
这可能是一个示例测试:
class TargetClass
{
public function testMeSomehow($id, Flag $flag)
{
return $flag->method1();
}
}
class TargetClassTest extends PHPUnit_Framework_TestCase
{
public function testSomething()
{
$mock = $this->getMock('Flag');
$mock->expects($this->once())
->method('method1')
->willReturn('methodResult');
$targetClass = new TargetClass();
$this->assertEquals('methodResult', $classToTest->testMeSomehow(1, $mock));
}
}
您可以将要由mock替换的方法指定为$this->getMock()
的第二个参数。因为我们根本不指定任何东西,所以它将替换所有方法,因此不必担心抽象方法
编辑:添加了访问常量的示例:
class ClassToTest
{
public function testMeSomehow($id, Flag $flag)
{
return $flag::NAME;
}
}
class FlagTest extends PHPUnit_Framework_TestCase
{
public function testStuff()
{
$mock = $this->getMock('Flag');
$classToTest = new ClassToTest();
$this->assertEquals('Flag name', $classToTest->testMeSomehow(1, $mock));
}
}
如果您希望在测试中为该常量指定一个特定值,我建议使用该常量创建一个子类,并将其用于模拟
编辑:添加了一个示例,其中包含用于指定动态常量值的变通方法
class Flag
{
const NAME = 'Flag name';
public function getName()
{
return static::NAME;
}
}
class TargetClass
{
public function testMeSomehow($id, Flag $flag)
{
return $flag->getName();
}
}
class TargetClassTest extends PHPUnit_Framework_TestCase
{
public function testSomething()
{
$mock = $this->getMock('Flag');
$mock->expects($this->any())
->method('getName')
->willReturn('New flag name');
$targetClass = new TargetClass();
$this->assertEquals('New flag name', $classToTest->testMeSomehow(1, $mock));
}
}
但是,这迫使您在任何地方都使用
getName()
方法,因此我个人更喜欢前面的建议:模拟具有更改值的子类。如果您先尝试怎么办?为什么您认为模拟抽象类不同于模拟普通类或接口?没错,但是看到$flags::NAME了吗?如何为模拟设置常量?我添加了一个访问常量的示例,这段代码适合我。不可能动态更改常量值。如果您真的想为不同的测试指定许多不同的值,我添加了一个变通方法,但是我会使用前面的解决方案。