douzheng0702 2017-01-22 14:41
浏览 140
已采纳

如何(单元)基于静态方法调用测试类行为?

I have these 2 classes :

AbstractTaskDispatcher

<?php

declare(strict_types=1);

namespace MyExample;

abstract class AbstractTaskDispatcher
{
    public final function getResult(Task $task) : Result
    {
        if($worker = $this->getWorker($task))
            return $worker->getResult();
        else
            return Result::getUnprocessableTaskResult();
    }

    abstract protected function getWorker(Task $task) : Worker;
}

?>

Result

<?php

declare(strict_types=1);

namespace MyExample;

class Result
{
    private $code;

    public function __construct(int $code = 0)
    {
        $this->code = $code;
    }

    public static function getUnprocessableTaskResult() : Result
    {
        return new Result(1000);
    }

    public function getCode() : int
    {
        return $this->code;
    }
}

?>

I want to write a unit test with PHPUnit to get sure that AbstractTaskDispatcher::getResult() returns Result::getUnprocessableTaskResult() if no suitable Worker is found to process the Task.

I dont want to do this :

  1. Arrange : $expectedResult = Result::getUnprocessableTaskResult();
  2. Act : $result = $dispatcherStub->getResult(New Task());
  3. Assert : assertEquals($result, $expectedResult);

Because it relies on Result class implementation and would not be a unit test.

I tried to do something :

<?php

    use PHPUnit\Framework\TestCase;
    use MyExample as ex;

    class AbstractDispatcherTest extends TestCase
    {
        public function test_getResultSouldReturnUnprocessableTaskResultIfNoWorkerFound()
        {
            $dispatcher = $this->getMockForAbstractClass(ex\AbstractDispatcher::class);
            $arbitraryCode = 6666;
            $expectedResult = new ex\Result($arbitraryCode);
            $resultClass = $this->getMockClass('Result', ['getUnprocessableTaskResult']);
            $resultClass::staticExpects($this->any())
                ->method('getUnprocessableTaskResult')
                ->will($this->returnValue($expectedResult));

            $result = $dispatcher->getResult(new ex\Task([]));

            $this->assertEquals($expectedResult, $result);
        }
    }

?>

But staticExpects() method was deprecated and no longer exists in current PHPUnit version.

How can I write this test ?

  • 写回答

1条回答 默认 最新

  • duangangpin078794 2017-01-23 17:58
    关注

    You can simply test as follow:

    public function test_getResultSouldReturnUnprocessableTaskResultIfNoWorkerFound()
    {
        $dispatcher = $this->getMockForAbstractClass(ex\AbstractTaskDispatcher::class);
        $dispatcher->expects($this->once())
            ->method('getWorker')
            ->willReturn(false);
    
        $result = $dispatcher->getResult(new ex\Task([]));
    
        // Unuseful: this is implicit by the method signature
        $this->assertInstanceOf(ex\Result::class, $result);
        $this->assertEquals(1000, $result->getCode());
    }
    

    NB: I change the method definition of the classe AbstractTaskDispatcher as follow in order to return a false value:

    /**
     * @param Task $task
     * @return Result|false The Result of the task or false if no suitable Worker is found to process the Task
     */
    abstract protected function getWorker(Task $task);
    

    EDIT:

    As You commented, you can't check as follow instead of hardcode the result code:

        $this->assertEquals(ex\Result::getUnprocessableTaskResult(), $result);
        // Or
        $this->assertEquals(ex\Result::getUnprocessableTaskResult()->getCode(), $result->getCode());
    

    Hope this help

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 python中合并修改日期相同的CSV文件并按照修改日期的名字命名文件
  • ¥15 有赏,i卡绘世画不出
  • ¥15 如何用stata画出文献中常见的安慰剂检验图
  • ¥15 c语言链表结构体数据插入
  • ¥40 使用MATLAB解答线性代数问题
  • ¥15 COCOS的问题COCOS的问题
  • ¥15 FPGA-SRIO初始化失败
  • ¥15 MapReduce实现倒排索引失败
  • ¥15 ZABBIX6.0L连接数据库报错,如何解决?(操作系统-centos)
  • ¥15 找一位技术过硬的游戏pj程序员