我在谈论这个功能:
function testMeSomehow ($id, Flag $flags)
{
$flags::NAME;
}
其参数对象:
abstract class Flag
{
abstract function method1();
abstract function method2();
.
.
.
abstract function method999();
}
如何模拟这个Flag
课程?它有大量的抽象方法,我应该用空体创建所有这些方法吗?如果这堂课改变怎么办?我还必须向其添加NAME
常量
答案 0 :(得分:2)
您可以使用测试双打来模拟它,就像您对其他任何课程一样,请参阅https://phpunit.de/manual/current/en/test-doubles.html
这可能是一个示例测试:
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));
}
}
您可以指定要将模拟替换为$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()
方法,所以我个人更喜欢以前的建议:模拟一个具有更改值的子类。