【问题标题】:Verify that one instance method calls another验证一个实例方法是否调用另一个
【发布时间】:2014-02-02 21:24:05
【问题描述】:

例如,我们有一个返回结果集的 cron 作业。我需要能够根据模拟结果集测试 runjobs 方法是否调用了正确的方法。

function runJobs($results) {
    foreach (results as $row) {
        if ($row->blah === 'condition') {
            $this->runJobA($row);
        } else {
            $this->runJobB($row);
        }
    }
}

function runJobA($row) {
    //do something
}

function runJobB($row) {
    //do something
}

【问题讨论】:

    标签: unit-testing mocking phpunit


    【解决方案1】:

    可以使用部分模拟来实现它。

    快速且未经测试的提案:

    $mock = $this->createMock('classname', array('runJobA', 'runJobB'));
    
    $mock->expects($this->once())
         ->method('runJobA');
    
    $mock->runJobs(...);
    

    如果您将特定方法名称指定为 createMock() 方法的第二个参数,则 phpunit 模拟库会生成所谓的部分模拟。

    与“普通”模拟相比 - 在部分模拟中,所有方法都使用现有的 real 实现,但您指定的那些将被模拟。

    【讨论】:

    • 我怀疑这是答案,但在我阅读本文时,我已经重构了我的代码以使用 gontrollez 解决方案。
    • @BobB:我会说公开要调用的方法只是为了让您的代码可测试是一种不好的做法
    【解决方案2】:

    获取类的决策代码:

    class JobSelector
    {
         public function getJobRunnerMethodName($results)
         {
             // some logic here for getting JobA or JobB
             $method = "runJobA";
             return $method;
         }
    }
    

    现在你可以测试它了:

    public function testJobAMethodReturnedWhenBlah()
    {
        $sut = new JobSelector();
        $result = "blah";
        $this->assertEquals('runJobA', $sut->getJob($result));
    }
    
    public function testJobBMethodReturnedWhenBlah()
    {
         ....
    }
    

    此外,您可以在其自己的类中实现每个作业,并使 JobSelector 类返回一个 Job 实例。然后您测试返回的作业类型而不是方法名称。你的代码会变成:

    $job_selector = new JobSelector();
    $job = $job_selector->getJob();
    $job->run();
    

    【讨论】:

    • 我重构了我的代码来完成这项工作。实际上并没有回答问题,但确实解决了我的问题,所以谢谢。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-30
    • 1970-01-01
    • 1970-01-01
    • 2016-11-16
    • 2020-10-15
    相关资源
    最近更新 更多