I want to functional-test a Symfony's command
I'm creating. I'm taking advantage of the Question
helper class, by associating a personal validator
:
$helper = $this->getHelper('question');
$question = new Question('Enter a valid IP: ');
$question->setValidator($domainValidator);
$question->setMaxAttempts(2);
the tests I'm performing are functionals, so in order to mock the interaction I added something like the following to my PHPUnit's test class. Here's an excerpt:
public function testBadIpRaisesError()
{
$question = $this->createMock('Symfony\Component\Console\Helper\QuestionHelper');
$question
->method('ask')
->will($this->onConsecutiveCalls(
'<IP>',
true
));
...
}
protected function createMock($originalClassName)
{
return $this->getMockBuilder($originalClassName)
->disableOriginalConstructor()
->disableOriginalClone()
->disableArgumentCloning()
->disallowMockingUnknownTypes()
->getMock();
}
of course this mock is more than ok when I'm testing something that goes beyond the Question
helper, but in this case what I'd like to do is testing the whole thing in order to make sure the validator is well written.
What's the best option in this case? Unit testing my validator is OK, but I would like to functional-testing it as a black box by the user point of view
The Console component provides a CommandTester
for precisely this use case: https://symfony.com/doc/current/console.html#testing-commands. You probably want to do something like this:
<?php
class ExampleCommandTest extends \PHPUnit\Framework\TestCase
{
public function testBadIpRaisesError()
{
// For a command 'bin/console example'.
$commandName = 'example';
// Set up your Application with your command.
$application = new \Symfony\Component\Console\Application();
// Here's where you would inject any mocked dependencies as needed.
$createdCommand = new WhateverCommand();
$application->add($createdCommand);
$foundCommand = $application->find($commandName);
// Create a CommandTester with your Command class processed by your Application.
$tester = new \Symfony\Component\Console\Tester\CommandTester($foundCommand);
// Respond "y" to the first prompt (question) when the command is invoked.
$tester->setInputs(['y']);
// Execute the command. This example would be the equivalent of
// 'bin/console example 127.0.0.1 --ipv6=true'
$tester->execute([
'command' => $commandName,
// Arguments as needed.
'ip-address' => '127.0.0.1',
// Options as needed.
'--ipv6' => true,
]);
self::assert('Example output', $tester->getDisplay());
self::assert(0, $tester->getStatusCode());
}
}
You can see some more sophisticated working examples in a project I'm working on: https://github.com/php-tuf/composer-stager/blob/v0.1.0/tests/Unit/Console/Command/StageCommandTest.php
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With