diff --git a/Makefile b/Makefile
index cc2f9fd9..8cf92810 100644
--- a/Makefile
+++ b/Makefile
@@ -104,10 +104,10 @@ tools/deptrac:
curl -Ls http://get.sensiolabs.de/deptrac.phar -o tools/deptrac && chmod +x tools/deptrac
tools/infection: tools/infection.pubkey
- curl -Ls https://github.com/infection/infection/releases/download/0.10.1/infection.phar -o tools/infection && chmod +x tools/infection
+ curl -Ls https://github.com/infection/infection/releases/download/0.10.3/infection.phar -o tools/infection && chmod +x tools/infection
tools/infection.pubkey:
- curl -Ls https://github.com/infection/infection/releases/download/0.10.1/infection.phar.pubkey -o tools/infection.pubkey
+ curl -Ls https://github.com/infection/infection/releases/download/0.10.3/infection.phar.pubkey -o tools/infection.pubkey
tools/box:
curl -Ls https://github.com/humbug/box/releases/download/3.0.0-RC.0/box.phar -o tools/box && chmod +x tools/box
diff --git a/README.md b/README.md
index 0044159a..d0c23cbf 100644
--- a/README.md
+++ b/README.md
@@ -39,12 +39,28 @@ curl -s https://api.github.com/repos/jakzal/toolbox/releases/latest \
./toolbox install
```
+#### Dry run
+
+To only see what commands would be executed, use the dry run mode:
+
+```
+./toolbox install --dry-run
+```
+
### Test if installed tools are usable
```
./toolbox test
```
+#### Dry run
+
+To only see what commands would be executed, use the dry run mode:
+
+```
+./toolbox test --dry-run
+```
+
### Tools definitions
By default `resources/pre-installation.json` and `resources/tools.json` are used to load tool definitions.
diff --git a/composer.json b/composer.json
index c17124d3..2dcaf49b 100644
--- a/composer.json
+++ b/composer.json
@@ -8,7 +8,8 @@
"psr/container": "^1.0"
},
"require-dev": {
- "phpunit/phpunit": "^7.3"
+ "phpunit/phpunit": "^7.3",
+ "zalas/phpunit-globals": "^1.1"
},
"autoload": {
"psr-4": {
diff --git a/phpunit.xml.dist b/phpunit.xml.dist
index d0528e28..461c6568 100644
--- a/phpunit.xml.dist
+++ b/phpunit.xml.dist
@@ -19,6 +19,10 @@
+
+
+
+
diff --git a/src/Cli/Application.php b/src/Cli/Application.php
index 027311a8..5a7c8307 100644
--- a/src/Cli/Application.php
+++ b/src/Cli/Application.php
@@ -2,6 +2,7 @@
namespace Zalas\Toolbox\Cli;
+use Psr\Container\ContainerInterface;
use Symfony\Component\Console\Application as CliApplication;
use Symfony\Component\Console\CommandLoader\CommandLoaderInterface;
use Symfony\Component\Console\CommandLoader\ContainerCommandLoader;
@@ -22,14 +23,13 @@ public function __construct(string $version, ServiceContainer $serviceContainer)
$this->serviceContainer = $serviceContainer;
- $this->setCommandLoader($this->createCommandLoader());
+ $this->setCommandLoader($this->createCommandLoader($serviceContainer));
}
public function doRun(InputInterface $input, OutputInterface $output)
{
- $this->serviceContainer->setParameter('toolbox_json', function () use ($input): array {
- return $input->getOption('tools');
- });
+ $this->serviceContainer->set(InputInterface::class, $input);
+ $this->serviceContainer->set(OutputInterface::class, $output);
return parent::doRun($input, $output);
}
@@ -49,10 +49,10 @@ private function toolsJsonDefault(): array
: [__DIR__.'/../../resources/pre-installation.json', __DIR__.'/../../resources/tools.json'];
}
- private function createCommandLoader(): CommandLoaderInterface
+ private function createCommandLoader(ContainerInterface $container): CommandLoaderInterface
{
return new ContainerCommandLoader(
- $this->serviceContainer,
+ $container,
[
InstallCommand::NAME => InstallCommand::class,
ListCommand::NAME => ListCommand::class,
diff --git a/src/Cli/Command/InstallCommand.php b/src/Cli/Command/InstallCommand.php
index 44beb937..406b995f 100644
--- a/src/Cli/Command/InstallCommand.php
+++ b/src/Cli/Command/InstallCommand.php
@@ -4,6 +4,7 @@
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Zalas\Toolbox\Runner\Runner;
use Zalas\Toolbox\UseCase\InstallTools;
@@ -26,6 +27,7 @@ public function __construct(InstallTools $useCase, Runner $runner)
protected function configure()
{
$this->setDescription('Installs tools');
+ $this->addOption('dry-run', null, InputOption::VALUE_NONE, 'Output the command without executing it');
}
protected function execute(InputInterface $input, OutputInterface $output)
diff --git a/src/Cli/Command/TestCommand.php b/src/Cli/Command/TestCommand.php
index 30db9830..0dd19e3b 100644
--- a/src/Cli/Command/TestCommand.php
+++ b/src/Cli/Command/TestCommand.php
@@ -4,6 +4,7 @@
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Zalas\Toolbox\Runner\Runner;
use Zalas\Toolbox\UseCase\TestTools;
@@ -26,6 +27,7 @@ public function __construct(TestTools $useCase, Runner $runner)
protected function configure()
{
$this->setDescription('Runs basic tests to verify tools are installed');
+ $this->addOption('dry-run', null, InputOption::VALUE_NONE, 'Output the command without executing it');
}
protected function execute(InputInterface $input, OutputInterface $output)
diff --git a/src/Cli/Runner/DryRunner.php b/src/Cli/Runner/DryRunner.php
new file mode 100644
index 00000000..244ca609
--- /dev/null
+++ b/src/Cli/Runner/DryRunner.php
@@ -0,0 +1,24 @@
+output = $output;
+ }
+
+ public function run(Command $command): int
+ {
+ $this->output->writeln((string) $command);
+
+ return 0;
+ }
+}
diff --git a/src/Cli/Runner/LazyRunner.php b/src/Cli/Runner/LazyRunner.php
new file mode 100644
index 00000000..abf2fdcc
--- /dev/null
+++ b/src/Cli/Runner/LazyRunner.php
@@ -0,0 +1,63 @@
+guardServiceAvailability($container);
+
+ $this->container = $container;
+ }
+
+ public function run(Command $command): int
+ {
+ return $this->runner()->run($command);
+ }
+
+ private function runner(): Runner
+ {
+ if (null === $this->runner) {
+ $this->runner = $this->initializeRunner();
+ }
+
+ return $this->runner;
+ }
+
+ private function initializeRunner(): Runner
+ {
+ if ($this->container->get(InputInterface::class)->getOption('dry-run')) {
+ return $this->container->get(DryRunner::class);
+ }
+
+ return $this->container->get(PassthruRunner::class);
+ }
+
+ private function guardServiceAvailability(ContainerInterface $container): void
+ {
+ $requiredServices = [
+ InputInterface::class,
+ PassthruRunner::class,
+ DryRunner::class,
+ ];
+
+ foreach ($requiredServices as $serviceId) {
+ if (!$container->has($serviceId)) {
+ throw new class(\sprintf('The service "%s" is missing.', $serviceId)) extends \LogicException implements ContainerExceptionInterface {
+ };
+ }
+ }
+ }
+}
diff --git a/src/Cli/ServiceContainer.php b/src/Cli/ServiceContainer.php
index d11e55da..fc452733 100644
--- a/src/Cli/ServiceContainer.php
+++ b/src/Cli/ServiceContainer.php
@@ -6,9 +6,13 @@
use Psr\Container\ContainerInterface;
use Psr\Container\NotFoundExceptionInterface;
use RuntimeException;
+use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Output\OutputInterface;
use Zalas\Toolbox\Cli\Command\InstallCommand;
use Zalas\Toolbox\Cli\Command\ListCommand;
use Zalas\Toolbox\Cli\Command\TestCommand;
+use Zalas\Toolbox\Cli\Runner\DryRunner;
+use Zalas\Toolbox\Cli\Runner\LazyRunner;
use Zalas\Toolbox\Json\JsonTools;
use Zalas\Toolbox\Runner\PassthruRunner;
use Zalas\Toolbox\Runner\Runner;
@@ -19,53 +23,57 @@
class ServiceContainer implements ContainerInterface
{
- private $parameters;
-
private $services = [
InstallCommand::class => 'createInstallCommand',
ListCommand::class => 'createListCommand',
TestCommand::class => 'createTestCommand',
Runner::class => 'createRunner',
+ DryRunner::class => 'createDryRunner',
+ PassthruRunner::class => 'createPassthruRunner',
InstallTools::class => 'createInstallToolsUseCase',
ListTools::class => 'createListToolsUseCase',
TestTools::class => 'createTestToolsUseCase',
Tools::class => 'createTools',
];
- /**
- * {@inheritdoc}
- */
- public function get($id)
+ private $runtimeServices = [
+ InputInterface::class => null,
+ OutputInterface::class => null,
+ ];
+
+ public function set(string $id, /*object */$service): void
{
- if (!$this->has($id)) {
- throw new class(\sprintf('The "%s" service is not registered in the service container.', $id)) extends \RuntimeException implements NotFoundExceptionInterface {
+ if (!\array_key_exists($id, $this->runtimeServices)) {
+ throw new class(\sprintf('The "%s" runtime service is not expected.', $id)) extends RuntimeException implements ContainerExceptionInterface {
};
}
- return \call_user_func([$this, $this->services[$id]]);
+ $this->runtimeServices[$id] = $service;
}
/**
* {@inheritdoc}
*/
- public function has($id)
+ public function get($id)
{
- return \in_array($id, \array_keys($this->services));
- }
+ if (isset($this->runtimeServices[$id])) {
+ return $this->runtimeServices[$id];
+ }
- public function setParameter(string $name, $value): void
- {
- $this->parameters[$name] = $value;
+ if (isset($this->services[$id])) {
+ return \call_user_func([$this, $this->services[$id]]);
+ }
+
+ throw new class(\sprintf('The "%s" service is not registered in the service container.', $id)) extends RuntimeException implements NotFoundExceptionInterface {
+ };
}
- private function getParameter(string $name)
+ /**
+ * {@inheritdoc}
+ */
+ public function has($id)
{
- if (!isset($this->parameters[$name])) {
- throw new class(\sprintf('The "%s" parameter is not defined.', $name)) extends RuntimeException implements ContainerExceptionInterface {
- };
- }
-
- return $this->parameters[$name];
+ return isset($this->services[$id]) || isset($this->runtimeServices[$id]);
}
private function createInstallCommand(): InstallCommand
@@ -84,10 +92,20 @@ private function createTestCommand(): TestCommand
}
private function createRunner(): Runner
+ {
+ return new LazyRunner($this);
+ }
+
+ private function createPassthruRunner(): Runner
{
return new PassthruRunner();
}
+ private function createDryRunner(): Runner
+ {
+ return new DryRunner($this->get(OutputInterface::class));
+ }
+
private function createInstallToolsUseCase(): InstallTools
{
return new InstallTools($this->get(Tools::class));
@@ -105,6 +123,8 @@ private function createTestToolsUseCase(): TestTools
private function createTools(): Tools
{
- return new JsonTools($this->getParameter('toolbox_json'));
+ return new JsonTools(function (): array {
+ return $this->get(InputInterface::class)->getOption('tools');
+ });
}
}
diff --git a/tests/Cli/ApplicationTest.php b/tests/Cli/ApplicationTest.php
index b8919f18..ccff7cca 100644
--- a/tests/Cli/ApplicationTest.php
+++ b/tests/Cli/ApplicationTest.php
@@ -3,11 +3,14 @@
namespace Zalas\Toolbox\Tests\Cli;
use PHPUnit\Framework\TestCase;
+use Prophecy\Argument;
use Prophecy\Prophecy\ObjectProphecy;
use Symfony\Component\Console\Application as CliApplication;
use Symfony\Component\Console\Input\ArrayInput;
use Symfony\Component\Console\Output\NullOutput;
+use Symfony\Component\Console\Output\OutputInterface;
use Zalas\Toolbox\Cli\Application;
+use Zalas\Toolbox\Cli\Command\InstallCommand;
use Zalas\Toolbox\Cli\Command\ListCommand;
use Zalas\Toolbox\Cli\ServiceContainer;
@@ -47,14 +50,20 @@ public function test_it_defines_tools_option()
$this->assertTrue($this->app->getDefinition()->hasOption('tools'));
}
+ /**
+ * @putenv TOOLBOX_JSON=resources/pre.json,resources/tools.json
+ */
+ public function test_it_takes_the_tools_option_default_from_environment_if_present()
+ {
+ $this->assertSame(['resources/pre.json', 'resources/tools.json'], $this->app->getDefinition()->getOption('tools')->getDefault());
+ }
+
/**
* @group integration
*/
public function test_it_allows_to_override_tools_location()
{
- $container = new ServiceContainer();
-
- $app = new Application(self::VERSION, $container);
+ $app = new Application(self::VERSION, new ServiceContainer());
$result = $app->doRun(
new ArrayInput([
'command' => ListCommand::NAME,
@@ -66,4 +75,28 @@ public function test_it_allows_to_override_tools_location()
$this->assertSame(0, $result);
}
+
+ /**
+ * @group integration
+ */
+ public function test_it_runs_the_command_in_dry_run_mode()
+ {
+ $output = $this->prophesize(OutputInterface::class);
+
+ $app = new Application(self::VERSION, new ServiceContainer());
+ $app->doRun(
+ new ArrayInput([
+ 'command' => InstallCommand::NAME,
+ '--dry-run' => true,
+ '--tools' => [__DIR__.'/../resources/tools.json'],
+ '--no-interaction' => true,
+ ]),
+ $output->reveal()
+ );
+
+ $output->writeln(Argument::allOf(
+ Argument::type('string'),
+ Argument::containingString('composer global bin phpstan require')
+ ))->shouldHaveBeenCalled();
+ }
}
diff --git a/tests/Cli/Command/InstallCommandTest.php b/tests/Cli/Command/InstallCommandTest.php
index fde32155..04e2d2f2 100644
--- a/tests/Cli/Command/InstallCommandTest.php
+++ b/tests/Cli/Command/InstallCommandTest.php
@@ -54,6 +54,11 @@ public function test_it_returns_the_status_code_of_the_run()
$this->assertSame(1, $tester->getStatusCode());
}
+ public function test_it_defines_dry_run_option()
+ {
+ $this->assertTrue($this->cliCommand()->getDefinition()->hasOption('dry-run'));
+ }
+
protected function getContainerTestDoubles(): array
{
return [
diff --git a/tests/Cli/Command/TestCommandTest.php b/tests/Cli/Command/TestCommandTest.php
index a1454365..e258dc85 100644
--- a/tests/Cli/Command/TestCommandTest.php
+++ b/tests/Cli/Command/TestCommandTest.php
@@ -54,6 +54,11 @@ public function test_it_returns_the_status_code_of_the_run()
$this->assertSame(1, $tester->getStatusCode());
}
+ public function test_it_defines_dry_run_option()
+ {
+ $this->assertTrue($this->cliCommand()->getDefinition()->hasOption('dry-run'));
+ }
+
protected function getContainerTestDoubles(): array
{
return [
diff --git a/tests/Cli/Command/ToolboxCommandTestCase.php b/tests/Cli/Command/ToolboxCommandTestCase.php
index 5e00d4fd..b02c3211 100644
--- a/tests/Cli/Command/ToolboxCommandTestCase.php
+++ b/tests/Cli/Command/ToolboxCommandTestCase.php
@@ -24,7 +24,7 @@ protected function setUp()
public function test_it_provides_help()
{
- $this->assertNotEmpty($this->findCliCommand()->getDescription());
+ $this->assertNotEmpty($this->cliCommand()->getDescription());
}
protected function getContainerTestDoubles(): array
@@ -34,13 +34,13 @@ protected function getContainerTestDoubles(): array
protected function executeCliCommand(array $input = []): CommandTester
{
- $tester = new CommandTester($this->findCliCommand());
+ $tester = new CommandTester($this->cliCommand());
$tester->execute($input);
return $tester;
}
- private function findCliCommand(): Command
+ protected function cliCommand(): Command
{
return $this->app->find(static::CLI_COMMAND_NAME);
}
diff --git a/tests/Cli/Runner/DryRunnerTest.php b/tests/Cli/Runner/DryRunnerTest.php
new file mode 100644
index 00000000..4c1cfb4c
--- /dev/null
+++ b/tests/Cli/Runner/DryRunnerTest.php
@@ -0,0 +1,48 @@
+out = $this->prophesize(OutputInterface::class);
+ $this->runner = new DryRunner($this->out->reveal());
+ }
+
+ public function test_it_is_a_runner()
+ {
+ $this->assertInstanceOf(Runner::class, $this->runner);
+ }
+
+ public function test_it_sends_the_command_to_the_output()
+ {
+ $result = $this->runner->run(new class implements Command {
+ public function __toString(): string
+ {
+ return 'echo "Foo"';
+ }
+ });
+
+ $this->out->writeln('echo "Foo"')->shouldHaveBeenCalled();
+
+ $this->assertSame(0, $result);
+ }
+}
diff --git a/tests/Cli/Runner/LazyRunnerTest.php b/tests/Cli/Runner/LazyRunnerTest.php
new file mode 100644
index 00000000..0ab6130c
--- /dev/null
+++ b/tests/Cli/Runner/LazyRunnerTest.php
@@ -0,0 +1,137 @@
+container = $this->prophesize(ContainerInterface::class);
+ $this->input = $this->prophesize(InputInterface::class);
+
+ $this->container->get(InputInterface::class)->willReturn($this->input);
+ $this->container->has(InputInterface::class)->willReturn(true);
+ $this->container->has(PassthruRunner::class)->willReturn(true);
+ $this->container->has(DryRunner::class)->willReturn(true);
+
+ $this->runner = new LazyRunner($this->container->reveal());
+ }
+
+ public function test_it_is_a_runner()
+ {
+ $this->assertInstanceOf(Runner::class, $this->runner);
+ }
+
+ public function test_it_runs_dry_runner_if_dry_run_option_is_present()
+ {
+ $command = $this->command();
+
+ $runner = $this->prophesize(Runner::class);
+ $runner->run($command)->willReturn(0);
+
+ $this->input->getOption('dry-run')->willReturn(true);
+ $this->container->get(DryRunner::class)->willReturn($runner);
+
+ $this->runner->run($command);
+
+ $runner->run($command)->shouldHaveBeenCalled();
+ }
+
+ public function test_it_returns_status_code_of_the_real_runner()
+ {
+ $command = $this->command();
+
+ $runner = $this->prophesize(Runner::class);
+ $runner->run($command)->willReturn(1);
+
+ $this->input->getOption('dry-run')->willReturn(true);
+ $this->container->get(DryRunner::class)->willReturn($runner);
+
+ $this->assertSame(1, $this->runner->run($command));
+ }
+
+ public function test_it_runs_passthru_runner_if_dry_run_option_is_absent()
+ {
+ $command = $this->command();
+
+ $runner = $this->prophesize(Runner::class);
+ $runner->run($command)->willReturn(0);
+
+ $this->input->getOption('dry-run')->willReturn(false);
+ $this->container->get(PassthruRunner::class)->willReturn($runner);
+
+ $this->runner->run($command);
+
+ $runner->run($command)->shouldHaveBeenCalled();
+ }
+
+ public function test_it_only_initializes_the_runner_once()
+ {
+ $command = $this->command();
+
+ $runner = $this->prophesize(Runner::class);
+ $runner->run($command)->willReturn(0);
+
+ $this->input->getOption('dry-run')->willReturn(false);
+ $this->container->get(PassthruRunner::class)->willReturn($runner);
+
+ $this->runner->run($command);
+ $this->runner->run($command);
+
+ $this->container->get(PassthruRunner::class)->shouldHaveBeenCalledTimes(1);
+ }
+
+ /**
+ * @dataProvider provideRequiredServices
+ */
+ public function test_it_complains_if_any_of_services_it_needs_from_the_container_are_not_defined(string $serviceId)
+ {
+ $this->expectException(ContainerExceptionInterface::class);
+ $this->expectExceptionMessage(\sprintf('The service "%s" is missing.', $serviceId));
+
+ $this->container->has($serviceId)->willReturn(false);
+ $this->container->get($serviceId)->willThrow(new class extends \RuntimeException implements NotFoundExceptionInterface {
+ });
+
+ new LazyRunner($this->container->reveal());
+ }
+
+ public function provideRequiredServices()
+ {
+ yield [InputInterface::class];
+ yield [PassthruRunner::class];
+ yield [DryRunner::class];
+ }
+
+ private function command(): Command
+ {
+ return $this->prophesize(Command::class)->reveal();
+ }
+}
diff --git a/tests/Cli/ServiceContainerTest.php b/tests/Cli/ServiceContainerTest.php
index 09be8300..f5028505 100644
--- a/tests/Cli/ServiceContainerTest.php
+++ b/tests/Cli/ServiceContainerTest.php
@@ -6,10 +6,16 @@
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\ContainerInterface;
use Psr\Container\NotFoundExceptionInterface;
+use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Output\OutputInterface;
use Zalas\Toolbox\Cli\Command\InstallCommand;
use Zalas\Toolbox\Cli\Command\ListCommand;
use Zalas\Toolbox\Cli\Command\TestCommand;
+use Zalas\Toolbox\Cli\Runner\DryRunner;
+use Zalas\Toolbox\Cli\Runner\LazyRunner;
use Zalas\Toolbox\Cli\ServiceContainer;
+use Zalas\Toolbox\Runner\PassthruRunner;
+use Zalas\Toolbox\Runner\Runner;
class ServiceContainerTest extends TestCase
{
@@ -21,9 +27,8 @@ class ServiceContainerTest extends TestCase
protected function setUp()
{
$this->container = new ServiceContainer();
- $this->container->setParameter('toolbox_json', function () {
- return [__DIR__.'/../resources/tools.json'];
- });
+ $this->container->set(InputInterface::class, $this->prophesize(InputInterface::class)->reveal());
+ $this->container->set(OutputInterface::class, $this->prophesize(OutputInterface::class)->reveal());
}
public function test_it_is_a_psr_container()
@@ -36,6 +41,25 @@ public function test_it_returns_false_if_service_is_not_registered()
$this->assertFalse($this->container->has('foo'));
}
+ /**
+ * @dataProvider provideApplicationServices
+ */
+ public function test_it_creates_application_services(string $serviceId, string $expectedType)
+ {
+ $this->assertTrue($this->container->has($serviceId));
+ $this->assertInstanceOf($expectedType, $this->container->get($serviceId));
+ }
+
+ public function provideApplicationServices()
+ {
+ yield [InstallCommand::class, InstallCommand::class];
+ yield [ListCommand::class, ListCommand::class];
+ yield [TestCommand::class, TestCommand::class];
+ yield [Runner::class, LazyRunner::class];
+ yield [DryRunner::class, DryRunner::class];
+ yield [PassthruRunner::class, PassthruRunner::class];
+ }
+
public function test_it_throws_an_exception_if_unregistered_service_is_accessed()
{
$this->expectException(NotFoundExceptionInterface::class);
@@ -44,30 +68,36 @@ public function test_it_throws_an_exception_if_unregistered_service_is_accessed(
$this->container->get('foo');
}
- public function test_it_throws_an_exception_if_toolbox_json_parameter_is_missing()
+ public function test_it_registers_a_runtime_service()
{
- $this->expectException(ContainerExceptionInterface::class);
- $this->expectExceptionMessage('The "toolbox_json" parameter is not defined.');
+ $service = $this->prophesize(InputInterface::class)->reveal();
- $this->container = new ServiceContainer();
- $this->container->get(InstallCommand::class);
+ $this->container->set(InputInterface::class, $service);
+
+ $this->assertTrue($this->container->has(InputInterface::class));
+ $this->assertSame($service, $this->container->get(InputInterface::class));
}
- public function test_it_creates_the_install_command()
+ public function test_it_returns_false_if_runtime_service_has_not_been_defined()
{
- $this->assertTrue($this->container->has(InstallCommand::class));
- $this->assertInstanceOf(InstallCommand::class, $this->container->get(InstallCommand::class));
+ $this->container = new ServiceContainer();
+
+ $this->assertFalse($this->container->has(InputInterface::class));
}
- public function test_it_creates_the_list_command()
+ public function test_it_throws_an_exception_if_missing_runtime_service_is_accessed()
{
- $this->assertTrue($this->container->has(ListCommand::class));
- $this->assertInstanceOf(ListCommand::class, $this->container->get(ListCommand::class));
+ $this->expectException(NotFoundExceptionInterface::class);
+
+ $this->container = new ServiceContainer();
+ $this->container->get(InputInterface::class);
}
- public function test_it_creates_the_test_command()
+ public function test_it_throws_an_exception_if_unknown_runtime_service_is_provided()
{
- $this->assertTrue($this->container->has(TestCommand::class));
- $this->assertInstanceOf(TestCommand::class, $this->container->get(TestCommand::class));
+ $this->expectException(ContainerExceptionInterface::class);
+ $this->expectExceptionMessage('The "foo" runtime service is not expected.');
+
+ $this->container->set('foo', new \stdClass());
}
}