使用 PHP 嘲笑模拟具体 class 时出错
Error mocking concrete class with PHP mockery
测试的class如下:
class ElasticSearchInstaller
{
/**
* Version of ElasticSearch
*
* @var \ElasticSearch\Requierments
*/
protected $requirements;
/**
* Object Constructor.
*
* @param Requierments $requirements
*/
public function __construct(Requirements $requirements)
{
$this->requirements = $requirements;
}
/**
* Set requirements
*
* @return bool
*/
public function canInstall()
{
return ($this->isInstalled() && $this->requirements->checkRequirements());
}
}
测试结果如下:
class ElasticSearchInstallerTest extends TestCase
{
/** @test **/
public function it_can_check_if_its_installable()
{
$requirements = m::mock('alias:ElasticSearch\Requirements');
$requirements->shouldReceive('checkRequirements')->once()->andReturn(true);
$installer = new ElasticSearchInstaller($requirements);
$this->assertInternalType('bool', $installer->canInstall());
}
}
虽然由于某种原因它没有通过,正如模拟所说 checkRequirements()
没有被调用并且期望被调用一次。
1) ElasticSearchInstallerTest::it_can_check_if_its_installable
Mockery\Exception\InvalidCountException: Method checkRequirements() from App\ElasticSearch\Requirements should be called
exactly 1 times but called 0 times.
编辑
问题是,如果 $this->isInstalled()
在 $this->requirements->checkRequirements()
之前调用,由于某种原因,在 canInstall()
中,例如上面的代码。它出错了。如果它换成:
public function canInstall()
{
return ($this->requirements->checkRequirements() && $this->isInstalled() );
}
...它通过了!卧槽?
问题是这样的布尔条件可以是快捷方式——如果 &&
(和)条件的第一部分为 FALSE,则 whoe 条件本身不能变为真,因此其余部分条件被跳过。函数调用被跳过,因此 运行 0 次。
因为在那个特定的测试中,您目前只测试整个条件,您可以模拟 ElasticSearchInstaller
的其余部分并做同样的事情:
$searchInstaller->shouldReceive('isInstalled')->andReturn(true);
模拟将退回到使用原始的 canInstall(),因此 运行 条件。尽管如此,它仍然几乎是一个过于简单而不会失败的案例 - 我会集中精力在其他地方进行测试。
测试的class如下:
class ElasticSearchInstaller
{
/**
* Version of ElasticSearch
*
* @var \ElasticSearch\Requierments
*/
protected $requirements;
/**
* Object Constructor.
*
* @param Requierments $requirements
*/
public function __construct(Requirements $requirements)
{
$this->requirements = $requirements;
}
/**
* Set requirements
*
* @return bool
*/
public function canInstall()
{
return ($this->isInstalled() && $this->requirements->checkRequirements());
}
}
测试结果如下:
class ElasticSearchInstallerTest extends TestCase
{
/** @test **/
public function it_can_check_if_its_installable()
{
$requirements = m::mock('alias:ElasticSearch\Requirements');
$requirements->shouldReceive('checkRequirements')->once()->andReturn(true);
$installer = new ElasticSearchInstaller($requirements);
$this->assertInternalType('bool', $installer->canInstall());
}
}
虽然由于某种原因它没有通过,正如模拟所说 checkRequirements()
没有被调用并且期望被调用一次。
1) ElasticSearchInstallerTest::it_can_check_if_its_installable
Mockery\Exception\InvalidCountException: Method checkRequirements() from App\ElasticSearch\Requirements should be called
exactly 1 times but called 0 times.
编辑
问题是,如果 $this->isInstalled()
在 $this->requirements->checkRequirements()
之前调用,由于某种原因,在 canInstall()
中,例如上面的代码。它出错了。如果它换成:
public function canInstall()
{
return ($this->requirements->checkRequirements() && $this->isInstalled() );
}
...它通过了!卧槽?
问题是这样的布尔条件可以是快捷方式——如果 &&
(和)条件的第一部分为 FALSE,则 whoe 条件本身不能变为真,因此其余部分条件被跳过。函数调用被跳过,因此 运行 0 次。
因为在那个特定的测试中,您目前只测试整个条件,您可以模拟 ElasticSearchInstaller
的其余部分并做同样的事情:
$searchInstaller->shouldReceive('isInstalled')->andReturn(true);
模拟将退回到使用原始的 canInstall(),因此 运行 条件。尽管如此,它仍然几乎是一个过于简单而不会失败的案例 - 我会集中精力在其他地方进行测试。