我正在掌握PHPUnit,到目前为止发现它很容易使用,但我遇到了一个导致我遇到困难的测试用例。
我正在编写针对一组接口的代码,这些接口需要实现对象(一些PHP,一些是自制的),而SUT需要一个输入对象来实现多个接口。例如:
class MyClass implements ArrayAccess, MyInterface
{
// ...
}
SUT做了这样的事情:
class ClassToBeTested
{
protected $obj = NULL;
public function __construct ($obj)
{
$this -> obj = $obj;
}
public function methodToBeTested ()
{
if ($this -> obj instanceof ArrayAccess)
&& ($this -> obj instanceof MyInterface)
{
// ...
}
}
public function otherMethodUnderTest ()
{
if ($this -> obj instanceof ArrayAccess)
{
// ...
}
else
if ($this -> obj instanceof MyInterface)
{
// ...
}
}
}
我可以从一个接口或另一个接口创建存根,但我不知道你是否可以创建一个实现它们的存根。
protected function setUp ()
{
$stubField = $this -> getMockBuilder ('ArrayAccess')
-> getMock ();
$this -> object = new ClassToBeTested ($stubField);
}
或
protected function setUp ()
{
$stubField = $this -> getMockBuilder ('MyInterface')
-> getMock ();
$this -> object = new ClassToBeTested ($stubField);
}
是否可以从接口列表生成存根,或者我是否必须存根实现预期接口的具体类?这本身就造成了困难,因为需要存根的类本身需要将另一个对象传递给它的构造函数,而我似乎无法使disableOriginalConstructor()或setConstructorArgs()工作我认为这是因为有问题的具体类本身并不实现构造函数,而是从超类继承它。我错过了一些明显的东西吗?
答案 0 :(得分:6)
您是否有权编辑原始代码?如果是这样,我将创建一个扩展ArrayAccess和MyInterface的新接口。这样你就可以存根/模拟一个对象来测试被测试的方法。
答案 1 :(得分:4)
对于未来,如果有人碰巧看到这个答案,这在PHPUnit 7中适用于我:
$mock = $this
->getMockBuilder([InterfaceA::class,InterfaceB::class])
->getMock();
答案 2 :(得分:2)
在应用程序代码库中创建一个界面让测试更快乐并不是一个好主意。我的意思是你可以创建这个界面,但如果你把它放在测试代码库中的某个地方会更好。例如,您可以将测试用例类之后的接口直接放在文件中
为了同时测试两个接口我在测试用例文件中创建了一个接口(它可以是任何其他地方)
interface ApiAwareAction implements ActionInterface, ApiAwareInterface
{
}
在我模仿那个班级之后:
$this->getMock('Payum\Tests\ApiAwareAction');