我正在尝试测试一个辅助函数,它接受process
的一些实例,一个带有单个抽象方法的抽象类function get_field_class(Form $form, $field) {
return $form->get_errors_for($field) ? 'error' : '';
}
(实际上并没有从测试函数调用)。
Form
我的问题是,如何模拟抽象的get_field_class
类,以便它被$form = $this->getMockForAbstractClass(Form::class)
->method('process')
->will($this->returnValue(true));
$this->assertEquals('error', $this->wrapper->get_field_class($form, 'foo'));
的类型注释接受?
$form = $this->getMockBuilder(Form::class)
->setMockClassName(Form::class)
->getMockForAbstractClass(Form::class)
// ...
这会引发TypeError:参数1 ...必须是Form的实例,PHPUnit \ Framework \ MockObject \ Builder \ InvocationMocker的实例
$form = $this->getMockBuilder(Form::class)
->disableAutoload()
->setMockClassName(Form::class)
->getMockForAbstractClass(Form::class)
// ...
这会抛出警告类“表单”已存在。 (警告会在我的配置中被提升为异常或错误,因此这不是一个可接受的解决方案。)
AppName
这只会引发警告:类“表单”不存在。
答案 0 :(得分:0)
在您的第一个不起作用的示例中,您实际上并未传递模拟对象。为了实现这一点,代码需要是:
$form = $this->getMockForAbstractClass(Form::class);
$form->expects($this->once())
->method('process')
->will($this->returnValue(true));
$this->assertEquals('error', $this->wrapper->get_field_class($form, 'foo'));
will()
返回一个PHPUnit用来验证模拟对象被正确调用的对象。
正如在评论中提到的,从MockBuilder调用中删除setMockClassName
将起作用。
$form = $this->getMockBuilder(Form::class)
->getMockForAbstractClass(Form::class);
再次使用此表单,您需要单独设置对process
的调用的期望。
您得到的错误是因为该类已经存在,并且PHP不允许您创建两个具有相同名称的类。您无需为此设置名称,因为PHPUnit将创建一个扩展您的Form
类的新对象。
看一下PHPUnit文档中的示例: https://phpunit.readthedocs.io/en/7.1/test-doubles.html#mocking-traits-and-abstract-classes
<?php
use PHPUnit\Framework\TestCase;
abstract class AbstractClass
{
public function concreteMethod()
{
return $this->abstractMethod();
}
public abstract function abstractMethod();
}
class AbstractClassTest extends TestCase
{
public function testConcreteMethod()
{
$stub = $this->getMockForAbstractClass(AbstractClass::class);
$stub->expects($this->any())
->method('abstractMethod')
->will($this->returnValue(true));
$this->assertTrue($stub->concreteMethod());
}
}
?>