Skip to content

Commit eda0376

Browse files
committed
Allow different set of services per test case
This fixes an edge case problem when using multiple kernels to create containers with different sets of services per test case. The current limitation is it only works per test case class. It does not work per test case test method (all services in test case class have to come from the same service locator).
1 parent 2bcaaa9 commit eda0376

File tree

5 files changed

+69
-7
lines changed

5 files changed

+69
-7
lines changed

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ deptrac: vendor/bin/deptrac
3434
.PHONY: deptrac
3535

3636
infection: vendor/bin/infection vendor/bin/infection.pubkey
37-
phpdbg -qrr ./vendor/bin/infection --no-interaction --formatter=progress --min-msi=87 --min-covered-msi=89 --ansi
37+
phpdbg -qrr ./vendor/bin/infection --no-interaction --formatter=progress --min-msi=89 --min-covered-msi=91 --ansi
3838
.PHONY: infection
3939

4040
phpunit: vendor/bin/phpunit

src/Symfony/Compiler/ExposeServicesForTestsPass.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
77
use Symfony\Component\DependencyInjection\ContainerBuilder;
8+
use Symfony\Component\DependencyInjection\ContainerInterface;
89
use Symfony\Component\DependencyInjection\Reference;
910
use Symfony\Component\DependencyInjection\ServiceLocator;
1011
use Zalas\Injector\PHPUnit\Symfony\Compiler\Discovery\PropertyDiscovery;
@@ -35,7 +36,7 @@ public function process(ContainerBuilder $container): void
3536
private function discoverServices(): array
3637
{
3738
return \array_reduce($this->propertyDiscovery->run(), function (array $services, Property $property) {
38-
$services[$property->getClassName()][$property->getServiceId()] = new Reference($property->getServiceId());
39+
$services[$property->getClassName()][$property->getServiceId()] = new Reference($property->getServiceId(), ContainerInterface::IGNORE_ON_INVALID_REFERENCE);
3940

4041
return $services;
4142
}, []);

tests/Symfony/Compiler/ExposeServicesForTestsPassTest.php

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
use Prophecy\Prophecy\ObjectProphecy;
88
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
99
use Symfony\Component\DependencyInjection\ContainerBuilder;
10+
use Symfony\Component\DependencyInjection\ContainerInterface;
1011
use Symfony\Component\DependencyInjection\Reference;
1112
use Symfony\Component\DependencyInjection\ServiceLocator;
1213
use Zalas\Injector\PHPUnit\Symfony\Compiler\Discovery\PropertyDiscovery;
@@ -58,12 +59,12 @@ public function test_it_registers_a_service_locator_for_each_test_case_requiring
5859
$this->assertFalse($container->getDefinition(TestCase1::class)->isPrivate(), 'The first test case service locator is registered as a public service.');
5960
$this->assertTrue($container->getDefinition(TestCase1::class)->isPublic(), 'The first test case service locator is registered as a public service.');
6061
$this->assertTrue($container->getDefinition(TestCase1::class)->hasTag('container.service_locator'), 'The first case service locator is tagged.');
61-
$this->assertEquals([Service1::class => new Reference(Service1::class), Service2::class => new Reference(Service2::class)], $container->getDefinition(TestCase1::class)->getArgument(0));
62+
$this->assertEquals([Service1::class => new Reference(Service1::class, ContainerInterface::IGNORE_ON_INVALID_REFERENCE), Service2::class => new Reference(Service2::class, ContainerInterface::IGNORE_ON_INVALID_REFERENCE)], $container->getDefinition(TestCase1::class)->getArgument(0));
6263
$this->assertTrue($container->hasDefinition(TestCase2::class), 'The second test case service locator is registered as a service.');
6364
$this->assertFalse($container->getDefinition(TestCase2::class)->isPrivate(), 'The second test case service locator is registered as a public service.');
6465
$this->assertTrue($container->getDefinition(TestCase2::class)->isPublic(), 'The second test case service locator is registered as a public service.');
6566
$this->assertTrue($container->getDefinition(TestCase2::class)->hasTag('container.service_locator'), 'The second test case service locator is tagged.');
66-
$this->assertEquals([Service2::class => new Reference(Service2::class)], $container->getDefinition(TestCase2::class)->getArgument(0));
67+
$this->assertEquals([Service2::class => new Reference(Service2::class, ContainerInterface::IGNORE_ON_INVALID_REFERENCE)], $container->getDefinition(TestCase2::class, ContainerInterface::IGNORE_ON_INVALID_REFERENCE)->getArgument(0));
6768
}
6869

6970
public function test_it_only_registers_a_service_locator_if_any_services_were_discovered()
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
<?php
2+
declare(strict_types=1);
3+
4+
namespace Zalas\Injector\PHPUnit\Tests\Symfony\TestCase\Fixtures;
5+
6+
use Symfony\Component\Config\Loader\LoaderInterface;
7+
use Symfony\Component\DependencyInjection\ContainerBuilder;
8+
use Symfony\Component\HttpKernel\Kernel;
9+
use Zalas\Injector\PHPUnit\Symfony\Compiler\Discovery\ClassFinder;
10+
use Zalas\Injector\PHPUnit\Symfony\Compiler\Discovery\PropertyDiscovery;
11+
use Zalas\Injector\PHPUnit\Symfony\Compiler\ExposeServicesForTestsPass;
12+
13+
class AnotherTestKernel extends Kernel
14+
{
15+
public function registerBundles()
16+
{
17+
return [];
18+
}
19+
20+
public function getCacheDir()
21+
{
22+
return \sys_get_temp_dir().'/ZalasPHPUnitInjector2/cache/'.$this->environment;
23+
}
24+
25+
public function getLogDir()
26+
{
27+
return \sys_get_temp_dir().'/ZalasPHPUnitInjector2/logs';
28+
}
29+
30+
/**
31+
* Loads the container configuration.
32+
*/
33+
public function registerContainerConfiguration(LoaderInterface $loader)
34+
{
35+
$loader->load(function (ContainerBuilder $container) use ($loader) {
36+
$container->register(Service1::class, Service1::class);
37+
});
38+
}
39+
40+
protected function build(ContainerBuilder $container)
41+
{
42+
if ('test' === $this->getEnvironment()) {
43+
$container->addCompilerPass(
44+
new ExposeServicesForTestsPass(
45+
new PropertyDiscovery(new ClassFinder(__DIR__ . '/../'))
46+
)
47+
);
48+
}
49+
}
50+
}

tests/Symfony/TestCase/SymfonyContainerTest.php

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
use Zalas\Injector\PHPUnit\TestCase\ServiceContainerTestCase;
1010
use Zalas\Injector\PHPUnit\Tests\Symfony\TestCase\Fixtures\Service1;
1111
use Zalas\Injector\PHPUnit\Tests\Symfony\TestCase\Fixtures\Service2;
12-
use Zalas\Injector\PHPUnit\Tests\Symfony\TestCase\Fixtures\TestKernel;
1312

1413
class SymfonyContainerTest extends TestCase implements ServiceContainerTestCase
1514
{
@@ -27,6 +26,9 @@ class SymfonyContainerTest extends TestCase implements ServiceContainerTestCase
2726
*/
2827
private $service2;
2928

29+
/**
30+
* @env KERNEL_CLASS=Zalas\Injector\PHPUnit\Tests\Symfony\TestCase\Fixtures\TestKernel
31+
*/
3032
public function test_it_initializes_the_container_by_booting_the_symfony_kernel()
3133
{
3234
$container = $this->createContainer();
@@ -38,8 +40,16 @@ public function test_it_initializes_the_container_by_booting_the_symfony_kernel(
3840
$this->assertInstanceOf(Service2::class, $container->get('foo.service2'));
3941
}
4042

41-
protected static function getKernelClass()
43+
/**
44+
* @env KERNEL_CLASS=Zalas\Injector\PHPUnit\Tests\Symfony\TestCase\Fixtures\AnotherTestKernel
45+
*/
46+
public function test_it_ignores_missing_services_when_registering_the_service_locator()
4247
{
43-
return TestKernel::class;
48+
$container = $this->createContainer();
49+
50+
$this->assertInstanceOf(ServiceLocator::class, $container, 'Full container is not exposed.');
51+
$this->assertTrue($container->has(Service1::class), 'The private service is available in tests.');
52+
$this->assertFalse($container->has('foo.service2'), 'The private service is available in tests.');
53+
$this->assertInstanceOf(Service1::class, $container->get(Service1::class));
4454
}
4555
}

0 commit comments

Comments
 (0)