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

时间:2017-01-22 14:41:03

标签: php unit-testing phpunit static-methods php-7

我有这两个班级:

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

?>

结果

<?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;
    }
}

?>

我想用PHPUnit编写单元测试,以确保如果找不到合适的Worker来处理任务,AbstractTaskDispatcher :: getResult()将返回Result :: getUnprocessableTaskResult()。

我不想这样做:

  1. 安排:$ expectedResult = Result :: getUnprocessableTaskResult();
  2. 法案:$ result = $ dispatcherStub-&gt; getResult(New Task());
  3. 断言:assertEquals($ result,$ expectedResult);
  4. 因为它依赖于Result类实现而不是单元测试。

    我试着做点什么:

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

    但是不推荐使用staticExpects()方法,并且在当前的PHPUnit版本中不再存在。

    我该怎么写这个测试?

1 个答案:

答案 0 :(得分:0)

您可以按照以下方式进行测试:

const input = 'abc۵۶۷';
const persianNums = '۰۱۲۳۴۵۶۷۸۹';
const arabicNums = '0123456789';

const convertedInput = input.split('').map(c => {
  const i = persianNums.indexOf(c);
  if (i >= 0) return arabicNums.charAt(i);
  else return c;
}).join('');
// convertedInput will now be 'abc567'

注意:我更改了classe 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()); } 的方法定义,如下所示,以便返回AbstractTaskDispatcher值:

false

编辑:

正如您所评论的那样,您无法检查以下内容而非硬编码结果代码:

/**
 * @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);

希望这个帮助