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

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

报告相同问题?

悬赏问题

  • ¥50 易语言把MYSQL数据库中的数据添加至组合框
  • ¥20 求数据集和代码#有偿答复
  • ¥15 关于下拉菜单选项关联的问题
  • ¥20 java-OJ-健康体检
  • ¥15 rs485的上拉下拉,不会对a-b<-200mv有影响吗,就是接受时,对判断逻辑0有影响吗
  • ¥15 使用phpstudy在云服务器上搭建个人网站
  • ¥15 应该如何判断含间隙的曲柄摇杆机构,轴与轴承是否发生了碰撞?
  • ¥15 vue3+express部署到nginx
  • ¥20 搭建pt1000三线制高精度测温电路
  • ¥15 使用Jdk8自带的算法,和Jdk11自带的加密结果会一样吗,不一样的话有什么解决方案,Jdk不能升级的情况