我试图对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;
}
}
}
非常感谢您尽可能好好阅读和回答!
答案 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'。
提取如您所见,断言完全集成到测试数据,模拟对象和业务中。