如何用PHPUnit测试Symfony命令的数据更新功能?
如何测试Symfony命令的数据更新操作
我正尝试编写一个测试类,用于测试Symfony命令执行时的数据更新操作,但不清楚如何编写功能测试。我需要了解在UpdateTrackedContainerCommandTest类中应编写哪些函数来验证数据已更新。在Symfony官方文档中未找到相关示例,希望能得到相关指导。
用于更新数据的Symfony命令类
#[AsCommand( name: 'app:update-data', description: 'Updating data', hidden: false )] class UpdateDataCommand extends Command { private $repository; private $apiService; private $dbManager; public function __construct( Repository $repository, ApiService $apiService, DbManager $dbManager ) { $this->repository = $repository; $this->apiService = $apiService; $this->dbManager = $dbManager; parent::__construct(); } protected function configure(): void { $this ->setHelp('This command allows you to update data...') ->setDescription('Updating data'); } protected function execute(InputInterface $input, OutputInterface $output): int { $repositoryData = $this->repository->findAll(); $isUpdatedData = false; foreach ($repositoryData as $dataRow) { $apiData = $this->apiService->getApiData($dataRow->getReference())['result'] ?? null; if ($apiData) { foreach ($apiData['result'] as $key => $row) { if ($row['id'] == $dataRow['id']) { $dataRow[$key] = $row[$key]; $this->dbManager->persist($dataRow); $isUpdatedData = true; } } } } if ($isUpdatedData) { $this->dbManager->flush(); } return Command::SUCCESS; } }
现有测试类
class UpdateTrackedContainerCommandTest extends KernelTestCase { public function testExecute(): CommandTester { $kernel = self::bootKernel(); $application = new Application($kernel); $command = $application->find('app:update-tracked-container'); $commandTester = new CommandTester($command); $commandTester->execute([]); $commandTester->assertCommandIsSuccessful(); return $commandTester; } }
测试方案与示例代码
针对你的需求,需要补充以下核心测试逻辑,覆盖数据更新的关键场景:
1. 测试数据成功更新
验证当API返回有效更新数据时,数据库中的记录确实被修改:
public function testDataIsUpdatedWhenApiReturnsNewData(): void { self::bootKernel(); $container = self::getContainer(); // 1. 准备测试数据:插入一条初始记录到数据库 $testData = new YourDataEntity(); $testData->setId(1); $testData->setReference('TEST_REF'); $testData->setSomeField('old_value'); // 替换为你实际需要更新的字段 $entityManager = $container->get(EntityManagerInterface::class); $entityManager->persist($testData); $entityManager->flush(); $entityManager->clear(); // 清除缓存,确保后续查询从数据库读取 // 2. 模拟ApiService的返回值 $mockApiService = $this->createMock(ApiService::class); $mockApiService->method('getApiData') ->with('TEST_REF') ->willReturn([ 'result' => [ ['id' => 1, 'someField' => 'new_value'] ] ]); // 替换容器中的ApiService为模拟对象 $container->set(ApiService::class, $mockApiService); // 3. 执行命令 $application = new Application(self::$kernel); $command = $application->find('app:update-data'); $commandTester = new CommandTester($command); $commandTester->execute([]); // 4. 验证命令执行成功 $commandTester->assertCommandIsSuccessful(); // 5. 从数据库重新查询记录,验证字段已更新 $updatedData = $entityManager->find(YourDataEntity::class, 1); $this->assertEquals('new_value', $updatedData->getSomeField()); }
2. 测试无更新时不执行flush
确保当没有数据需要更新时,不会调用数据库的flush操作:
public function testFlushIsNotCalledWhenNoDataNeedsUpdate(): void { self::bootKernel(); $container = self::getContainer(); // 1. 准备测试数据 $testData = new YourDataEntity(); $testData->setId(1); $testData->setReference('TEST_REF'); $testData->setSomeField('current_value'); $entityManager = $container->get(EntityManagerInterface::class); $entityManager->persist($testData); $entityManager->flush(); $entityManager->clear(); // 2. 模拟ApiService返回无匹配数据 $mockApiService = $this->createMock(ApiService::class); $mockApiService->method('getApiData') ->with('TEST_REF') ->willReturn(['result' => []]); $container->set(ApiService::class, $mockApiService); // 3. 模拟DbManager,验证flush是否被调用 $mockDbManager = $this->createMock(DbManager::class); $mockDbManager->expects($this->never())->method('flush'); $container->set(DbManager::class, $mockDbManager); // 4. 执行命令 $application = new Application(self::$kernel); $command = $application->find('app:update-data'); $commandTester = new CommandTester($command); $commandTester->execute([]); $commandTester->assertCommandIsSuccessful(); }
3. 测试无API数据时不更新
验证当API返回空结果时,数据不会被修改:
public function testDataRemainsUnchangedWhenApiReturnsNull(): void { self::bootKernel(); $container = self::getContainer(); // 1. 准备测试数据 $testData = new YourDataEntity(); $testData->setId(1); $testData->setReference('TEST_REF'); $testData->setSomeField('original_value'); $entityManager = $container->get(EntityManagerInterface::class); $entityManager->persist($testData); $entityManager->flush(); $entityManager->clear(); // 2. 模拟ApiService返回null $mockApiService = $this->createMock(ApiService::class); $mockApiService->method('getApiData') ->with('TEST_REF') ->willReturn(null); $container->set(ApiService::class, $mockApiService); // 3. 执行命令 $application = new Application(self::$kernel); $command = $application->find('app:update-data'); $commandTester = new CommandTester($command); $commandTester->execute([]); // 4. 验证数据未被修改 $unchangedData = $entityManager->find(YourDataEntity::class, 1); $this->assertEquals('original_value', $unchangedData->getSomeField()); }
注意事项
- 替换代码中的
YourDataEntity为你实际使用的实体类 - 测试前确保数据库处于干净状态,可使用PHPUnit的
setUp/tearDown方法清理数据 - 如果使用Doctrine,可利用
SchemaTool在测试前重建数据库表,避免数据污染
内容的提问来源于stack exchange,提问作者Andrej Kozlovský
相关产品推荐
相关产品推荐

