如何对PHP命令类进行单元测试

时间:2015-10-30 08:48:35

标签: php unit-testing

我试图对PHP应用程序进行单元测试。 我也是单元测试的新手,也许这不应该是我的第一个单元测试用例之一,但我仍然需要完成这个,所以......

我有一个带有2个方法的PHP命令类和一个__construct()。 执行方法遍历一个数组(通过DBAL读取获得)并调用 executeSingleRow ,它读取数据库,进行一些考虑,并且,只要满足一些条件,调用另一个命令的execute方法。

我无法弄清楚如何在这里完成良好的单元测试,或者我应该如何修改代码。

以下是我的班级方法:

public function __construct(
    $registry,
    $firstTableRepository,
    $secondTableRepository,
    AnotherCommand $anotherCommand,
    JobLogRepository $logger = null
)
{
    $this->registry = $registry;
    $this->stagione = $this->registry->get('stagione');
    $this->firstTableRepository = $firstTableRepository;
    $this->secondTableRepository = $secondTableRepository;
    $this->anotherCommand= $anotherCommand;
    $this->logger = $logger;
    $this->error = false;
}

public function execute($toReplace, $replacer, $selected)
{
    foreach ($selected as $selectedRow) {
        firstTableID = $selectedRow['ID'];
        $this->executeSingleRow($toReplace, $replacer, firstTableID);
    }
    if ($this->error) {
        $this->keyException(null, 'Procedura terminata con errori');
    }
}


public function executeSingleRow($toReplace, $replacer, firstTableID)
{
    if ($toReplace == $replacer) {
        $this->error = true;
    } else {
        $firstTableRow = $this->firstTableRepository->readByID(firstTableID);
        if (!empty($firstTableRow)) {
            $CODE = $firstTableRow['CODE'];
            $newCODE = str_replace($toReplace, $replacer, $CODE);
            if ($newCODE != $CODE) {
                $articoloNuovo = $this->secondTableRepository->readByCode($newCODE);
                if ($articoloNuovo) {
                    $secondTableIDNuovo = $articoloNuovo['secondTableID'];
                    try {
                        $this->anotherCommand->setJobLog($this->jobLog);
                        $this->anotherCommand->execute($secondTableIDNuovo, 'G', firstTableID);
                        return;
                    } catch (\Exception $e) {
                        $this->error = true;
                    }
                } else {
                    $this->error = true;
                }
            } else {
                $this->error = true;
            }
        } else {
            $this->error = true;
        }
    }
}

非常感谢您尽可能好好阅读和回答!

1 个答案:

答案 0 :(得分:0)

首先,必须有一个类API,它永远不会改变你的包的矿工版本。那么,假设有一个带有以下API的Executor类(建议使用类激活的接口)

class CommandExecutor {
  public function __construct(
    $registry,
    $firstTableRepository,
    $secondTableRepository,
    AnotherCommand $anotherCommand,
    JobLogRepository $logger = null) {...}

  public function execute($toReplace, $replacer, $selected){..}
}

在第一步(测试设计之后),需要一个生成测试数据的模拟对象。

class RegistryMock {}
class TableRepositoryMock{}
class AnotherCommandMock{}

Mock类生成固定数据,因此您知道firstId,secondId是什么。如果AnotherCommandMock只是保存命令,一个简单的单元测试是:

$registryMock = new RegistryMock();
$ftrMock = new TableRepositoryMock($mockData);
$strMock = new TableRepositoryMock($mockData);
$aCommand = new AnotherCommandMock();
... 
$object = new CommandExecutor($registryMock, $ftrMock, $strMock, $aCommand);
$object->execute('%Code%', 'TestCode', 'testId1');
$aCommand->assertExecute('testId2', 'G', 'testId1');

其中$ testData包含testId1,代码为'代码:%Code%'和testId2由代码'代码:TestCode'。

提取

如您所见,断言完全集成到测试数据,模拟对象和业务中。