Skip to content

Fix #27523: throw informative errors in setup:db:generate-patch #27579

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,9 @@ protected function execute(InputInterface $input, OutputInterface $output): int
}
$type = $input->getOption(self::INPUT_KEY_PATCH_TYPE);
$modulePath = $this->componentRegistrar->getPath(ComponentRegistrar::MODULE, $moduleName);
if (null === $modulePath) {
throw new \InvalidArgumentException(sprintf('Cannot find a registered module with name "%s"', $moduleName));
}
$preparedModuleName = str_replace('_', '\\', $moduleName);
$preparedType = ucfirst($type);
$patchInterface = sprintf('%sPatchInterface', $preparedType);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/

namespace Magento\Developer\Test\Unit\Console\Command;

use Magento\Developer\Console\Command\GeneratePatchCommand;
use Magento\Framework\Component\ComponentRegistrar;
use Magento\Framework\Filesystem\Directory\Read;
use Magento\Framework\Filesystem\Directory\ReadFactory;
use Magento\Framework\Filesystem\Directory\Write;
use Magento\Framework\Filesystem\Directory\WriteFactory;
use Magento\Framework\Filesystem\DirectoryList;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Console\Tester\CommandTester;

class GeneratePatchCommandTest extends TestCase
{
/**
* @var ComponentRegistrar|MockObject
*/
private $componentRegistrarMock;

/**
* @var DirectoryList|MockObject
*/
private $directoryListMock;

/**
* @var ReadFactory|MockObject
*/
private $readFactoryMock;

/**
* @var WriteFactory|MockObject
*/
private $writeFactoryMock;

/**
* @var GeneratePatchCommand|MockObject
*/
private $command;

protected function setUp(): void
{
$this->componentRegistrarMock = $this->createMock(ComponentRegistrar::class);
$this->directoryListMock = $this->createMock(DirectoryList::class);
$this->readFactoryMock = $this->createMock(ReadFactory::class);
$this->writeFactoryMock = $this->createMock(WriteFactory::class);

$this->command = new GeneratePatchCommand(
$this->componentRegistrarMock,
$this->directoryListMock,
$this->readFactoryMock,
$this->writeFactoryMock
);
}

public function testExecute()
{
$this->componentRegistrarMock->expects($this->once())
->method('getPath')
->with('module', 'Vendor_Module')
->willReturn('/long/path/to/Vendor/Module');

$read = $this->createMock(Read::class);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @korostii. Thank you for fixing the issues mentioned earlier. There was a comment from me regarding suffixing mock properties with Mock suffix. The same applies to the variables. This suffix improves code readability by letting know straight away what object we are working on mock or a real instance.

Just a recommendation for the future 😉

$read->expects($this->at(0))
->method('readFile')
->with('patch_template.php.dist')
->willReturn('something');
$this->readFactoryMock->method('create')->willReturn($read);

$write = $this->createMock(Write::class);
$write->expects($this->once())->method('writeFile');
$this->writeFactoryMock->method('create')->willReturn($write);

$this->directoryListMock->expects($this->once())->method('getRoot')->willReturn('/some/path');

$commandTester = new CommandTester($this->command);
$commandTester->execute(
[
GeneratePatchCommand::MODULE_NAME => 'Vendor_Module',
GeneratePatchCommand::INPUT_KEY_PATCH_NAME => 'SomePatch'
]
);
$this->assertStringContainsString('successfully generated', $commandTester->getDisplay());
}

public function testWrongParameter()
{
$this->expectExceptionMessage('Not enough arguments');
$this->expectException(\RuntimeException::class);

$commandTester = new CommandTester($this->command);
$commandTester->execute([]);
}

public function testBadModule()
{
$this->componentRegistrarMock->expects($this->once())
->method('getPath')
->with('module', 'Fake_Module')
->willReturn(null);

$this->expectExceptionMessage('Cannot find a registered module with name "Fake_Module"');
$this->expectException(\InvalidArgumentException::class);

$commandTester = new CommandTester($this->command);
$commandTester->execute(
[
GeneratePatchCommand::MODULE_NAME => 'Fake_Module',
GeneratePatchCommand::INPUT_KEY_PATCH_NAME => 'SomePatch'
]
);
}
}