简体   繁体   English

使用PHP模拟嘲笑具体类时出错

[英]Error mocking concrete class with PHP mockery

The class under test is as follows: 被测类如下:

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());
    }   
}

The test looks as follows: 该测试如下所示:

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());
    }    
}

Although for some reason it does not pass, as the mock says checkRequirements() is not being called and expects to be called once. 尽管由于某种原因它没有通过,但正如模拟所说的那样, 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.

EDIT The problem was, within canInstall() for some reason if $this->isInstalled() is called before $this->requirements->checkRequirements() such as in the code above. 编辑的问题是,内canInstall()由于某种原因,如果$this->isInstalled()之前被调用$this->requirements->checkRequirements()如在上面的代码。 It errors. 错误。 if its swapped to: 如果将其交换为:

public function canInstall() 
{
    return ($this->requirements->checkRequirements() && $this->isInstalled() );
}  

...it passes! ...它过去了! wtf? wtf?

The issue is that such boolean conditions can be shortcut -if the first part of an && (and) condition is FALSE, the whoe condition itself cannot become true, and so the rest of the parts of the conditional is skipped. 问题是这种布尔条件可以是快捷方式-如果&& (and)条件的第一部分为FALSE,则whoe条件本身无法变为真,因此该条件的其余部分将被跳过。 The function call was skipped, hence, run 0 times. 该函数调用被跳过,因此运行0次。

Since, in that specific test, you only only currently testing the condition as a whole, you can mock the rest of the ElasticSearchInstaller and do much the same: 由于在该特定测试中,您仅当前仅对整个条件进行了测试,因此您可以模拟其余的ElasticSearchInstaller并执行相同的操作:

$searchInstaller->shouldReceive('isInstalled')->andReturn(true); 

The mock would fall back to use the original canInstall(), and so run the condition. 该模拟将回退以使用原始的canInstall(),然后运行该条件。 It's still almost a too-simple-to-fail case though - I'd concentrate elsewhere for testing. 但是,这仍然几乎是一个太简单到无法通过的案例-我将精力集中在其他地方进行测试。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM