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

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

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

    已采纳该答案
    评论
    解决 无用
    打赏 举报

相关推荐 更多相似问题