【发布时间】:2012-12-19 03:34:54
【问题描述】:
我正在尝试测试扩展 Symfony\Component\Form\AbstractType 的类,但在使用 PHPUnit 模拟对象测试所需的 buildForm 方法时遇到问题:
class PageType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('name', 'text');
}
// ...
}
这是一些示例测试代码:
public function testBuildForm()
{
$form = new PageType($this->manager);
$formBuilder = $this->getMock('Symfony\Component\Form\FormBuilderInterface');
$form->buildForm($formBuilder, array());
}
很遗憾,对getMock() 的调用失败:
PHP Fatal error: Class Mock_FormBuilderInterface_f36f83d4 must implement interface Traversable as part of either Iterator or IteratorAggregate in Unknown on line 0
我怀疑我可能遇到了这个错误: https://github.com/sebastianbergmann/phpunit/issues/604
所以,我创建了一个界面来解决这个问题:
use Symfony\Component\Form\FormBuilderInterface;
interface FormBuilderInterfaceExtender extends \Iterator, FormBuilderInterface
{
}
并更改了我的测试代码:
public function testBuildForm()
{
$form = new PageType($this->manager);
$formBuilder = $this->getMock('Pwn\ContentBundle\Tests\Helper\FormBuilderInterfaceExtender');
$form->buildForm($formBuilder, array());
}
现在我有一个 FormBuilder 实例,但 PHP 不认为它是 Symfony\Component\Form\FormBuilderInterface 的实例,所以 $form->buildForm() 中的类型提示给出了这个错误:
Argument 1 passed to Pwn\ContentBundle\Form\Type\PageType::buildForm() must be an instance of Symfony\Component\Form\FormBuilderInterface, instance of Mock_FormBuilderInterfaceExtender_3527f313 given
在其他情况下,当我使用模拟对象时,类型提示和 instanceof 可以正常工作,但在这里却不行:
var_dump($formBuilder);
var_dump($formBuilder instanceof \Symfony\Component\Form\FormBuilderInterface);
给予
class Mock_FormBuilderInterfaceExtender_76df04af#19 (1) {
private $__phpunit_invocationMocker =>
NULL
}
bool(false)
看来我可以通过模拟一个实现接口的类来完成这项工作:
$formBuilder = $this->getMockBuilder('Symfony\Component\Form\FormBuilder')
->disableOriginalConstructor()
->getMock();
var_dump($formBuilder instanceof \Symfony\Component\Form\FormBuilderInterface);
// ^ gives bool(true)
但是,我应该能够使用界面本身吗?为什么扩展接口会“丢失”类型提示?
【问题讨论】:
-
你试过
assertInstanceOf而不是instanceof吗?在this thread 达到顶峰。 -
刚试过,不过assertInstanceOf只是instanceof的一种方便的使用方式,所以效果是一样的。
-
认为那里可能有一些魔法(你永远不会知道 w/ phpUnit)!我做了一个试金石(见下面的答案),看起来这应该有效,所以可能有点微妙。
-
你试过
getMock('Symfony\Component\Form\Tests\FormBuilderInterface')吗?