[FrameworkBundle] Add KernelTestCase::getContainer()

This commit is contained in:
Nyholm 2021-03-04 20:58:08 +01:00 committed by Fabien Potencier
parent 33791925af
commit f4c97240ff
21 changed files with 123 additions and 40 deletions

View File

@ -35,6 +35,7 @@ FrameworkBundle
* Deprecate the `session.storage` alias and `session.storage.*` services, use the `session.storage.factory` alias and `session.storage.factory.*` services instead
* Deprecate the `framework.session.storage_id` configuration option, use the `framework.session.storage_factory_id` configuration option instead
* Deprecate the `session` service and the `SessionInterface` alias, use the `\Symfony\Component\HttpFoundation\Request::getSession()` or the new `\Symfony\Component\HttpFoundation\RequestStack::getSession()` methods instead
* Deprecate the `KernelTestCase::$container` property, use `KernelTestCase::getContainer()` instead
HttpFoundation
--------------

View File

@ -78,6 +78,7 @@ FrameworkBundle
* The `form.factory`, `form.type.file`, `translator`, `security.csrf.token_manager`, `serializer`,
`cache_clearer`, `filesystem` and `validator` services are now private.
* Removed the `lock.RESOURCE_NAME` and `lock.RESOURCE_NAME.store` services and the `lock`, `LockInterface`, `lock.store` and `PersistingStoreInterface` aliases, use `lock.RESOURCE_NAME.factory`, `lock.factory` or `LockFactory` instead.
* Remove the `KernelTestCase::$container` property, use `KernelTestCase::getContainer()` instead
HttpFoundation
--------------

View File

@ -16,6 +16,7 @@ CHANGELOG
* Add tag `assets.package` to register asset packages
* Add support to use a PSR-6 compatible cache for Doctrine annotations
* Deprecate all other values than "none", "php_array" and "file" for `framework.annotation.cache`
* Add `KernelTestCase::getContainer()` as the best way to get a container in tests
5.2.0
-----

View File

@ -13,6 +13,7 @@ namespace Symfony\Bundle\FrameworkBundle\Test;
use PHPUnit\Framework\TestCase;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException;
use Symfony\Component\HttpKernel\KernelInterface;
use Symfony\Contracts\Service\ResetInterface;
@ -34,6 +35,8 @@ abstract class KernelTestCase extends TestCase
/**
* @var ContainerInterface
*
* @deprecated since Symfony 5.3, use static::getContainer() instead
*/
protected static $container;
@ -86,6 +89,27 @@ abstract class KernelTestCase extends TestCase
return static::$kernel;
}
/**
* Provides a dedicated test container with access to both public and private
* services. The container will not include private services that has been
* inlined or removed. Private services will be removed when they are not
* used by other services.
*
* Using this method is the best way to get a container from your test code.
*/
protected static function getContainer(): ContainerInterface
{
if (!static::$booted) {
static::bootKernel();
}
try {
return self::$kernelContainer->get('test.service_container');
} catch (ServiceNotFoundException $e) {
throw new \LogicException('Could not find service "test.service_container". Try updating the "framework.test" config to "true".', 0, $e);
}
}
/**
* Creates a Kernel.
*

View File

@ -118,12 +118,13 @@ trait MailerAssertionsTrait
private static function getMessageMailerEvents(): MessageEvents
{
if (self::$container->has('mailer.message_logger_listener')) {
return self::$container->get('mailer.message_logger_listener')->getEvents();
$container = static::getContainer();
if ($container->has('mailer.message_logger_listener')) {
return $container->get('mailer.message_logger_listener')->getEvents();
}
if (self::$container->has('mailer.logger_message_listener')) {
return self::$container->get('mailer.logger_message_listener')->getEvents();
if ($container->has('mailer.logger_message_listener')) {
return $container->get('mailer.logger_message_listener')->getEvents();
}
static::fail('A client must have Mailer enabled to make email assertions. Did you forget to require symfony/mailer?');

View File

@ -17,6 +17,11 @@ use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
use Symfony\Component\HttpKernel\KernelInterface;
/**
* A special container used in tests. This gives access to both public and
* private services. The container will not include private services that has
* been inlined or removed. Private services will be removed when they are not
* used by other services.
*
* @author Nicolas Grekas <p@tchwork.com>
*
* @internal

View File

@ -25,7 +25,7 @@ class AutowiringTypesTest extends AbstractWebTestCase
{
static::bootKernel(['root_config' => 'no_annotations_cache.yml', 'environment' => 'no_annotations_cache']);
$annotationReader = static::$container->get('test.autowiring_types.autowired_services')->getAnnotationReader();
$annotationReader = self::getContainer()->get('test.autowiring_types.autowired_services')->getAnnotationReader();
$this->assertInstanceOf(AnnotationReader::class, $annotationReader);
}
@ -33,7 +33,7 @@ class AutowiringTypesTest extends AbstractWebTestCase
{
static::bootKernel();
$annotationReader = static::$container->get('test.autowiring_types.autowired_services')->getAnnotationReader();
$annotationReader = self::getContainer()->get('test.autowiring_types.autowired_services')->getAnnotationReader();
$this->assertInstanceOf(class_exists(PsrCachedReader::class) ? PsrCachedReader::class : CachedReader::class, $annotationReader);
}
@ -41,12 +41,12 @@ class AutowiringTypesTest extends AbstractWebTestCase
{
static::bootKernel(['debug' => false]);
$autowiredServices = static::$container->get('test.autowiring_types.autowired_services');
$autowiredServices = self::getContainer()->get('test.autowiring_types.autowired_services');
$this->assertInstanceOf(EventDispatcher::class, $autowiredServices->getDispatcher(), 'The event_dispatcher service should be injected if the debug is not enabled');
static::bootKernel(['debug' => true]);
$autowiredServices = static::$container->get('test.autowiring_types.autowired_services');
$autowiredServices = self::getContainer()->get('test.autowiring_types.autowired_services');
$this->assertInstanceOf(TraceableEventDispatcher::class, $autowiredServices->getDispatcher(), 'The debug.event_dispatcher service should be injected if the debug is enabled');
}
@ -54,7 +54,7 @@ class AutowiringTypesTest extends AbstractWebTestCase
{
static::bootKernel();
$autowiredServices = static::$container->get('test.autowiring_types.autowired_services');
$autowiredServices = self::getContainer()->get('test.autowiring_types.autowired_services');
$this->assertInstanceOf(FilesystemAdapter::class, $autowiredServices->getCachePool());
}

View File

@ -40,8 +40,8 @@ class BundlePathsTest extends AbstractWebTestCase
public function testBundleTwigTemplatesDir()
{
static::bootKernel(['test_case' => 'BundlePaths']);
$twig = static::$container->get('twig.alias');
$bundlesMetadata = static::$container->getParameter('kernel.bundles_metadata');
$twig = static::getContainer()->get('twig.alias');
$bundlesMetadata = static::getContainer()->getParameter('kernel.bundles_metadata');
$this->assertSame([$bundlesMetadata['LegacyBundle']['path'].'/Resources/views'], $twig->getLoader()->getPaths('Legacy'));
$this->assertSame("OK\n", $twig->render('@Legacy/index.html.twig'));
@ -53,7 +53,7 @@ class BundlePathsTest extends AbstractWebTestCase
public function testBundleTranslationsDir()
{
static::bootKernel(['test_case' => 'BundlePaths']);
$translator = static::$container->get('translator.alias');
$translator = static::getContainer()->get('translator.alias');
$this->assertSame('OK', $translator->trans('ok_label', [], 'legacy'));
$this->assertSame('OK', $translator->trans('ok_label', [], 'modern'));
@ -62,7 +62,7 @@ class BundlePathsTest extends AbstractWebTestCase
public function testBundleValidationConfigDir()
{
static::bootKernel(['test_case' => 'BundlePaths']);
$validator = static::$container->get('validator.alias');
$validator = static::getContainer()->get('validator.alias');
$this->assertTrue($validator->hasMetadataFor(LegacyPerson::class));
$this->assertCount(1, $constraintViolationList = $validator->validate(new LegacyPerson('john', 5)));
@ -76,7 +76,7 @@ class BundlePathsTest extends AbstractWebTestCase
public function testBundleSerializationConfigDir()
{
static::bootKernel(['test_case' => 'BundlePaths']);
$serializer = static::$container->get('serializer.alias');
$serializer = static::getContainer()->get('serializer.alias');
$this->assertEquals(['full_name' => 'john', 'age' => 5], $serializer->normalize(new LegacyPerson('john', 5), 'json'));
$this->assertEquals(['full_name' => 'john', 'age' => 5], $serializer->normalize(new ModernPerson('john', 5), 'json'));

View File

@ -80,7 +80,7 @@ class CachePoolClearCommandTest extends AbstractWebTestCase
{
$tester = $this->createCommandTester();
/** @var FilesystemAdapter $pool */
$pool = static::$container->get('cache.public_pool');
$pool = static::getContainer()->get('cache.public_pool');
$item = $pool->getItem('foo');
$item->set('baz');
$pool->save($item);
@ -108,7 +108,7 @@ class CachePoolClearCommandTest extends AbstractWebTestCase
private function createCommandTester()
{
$application = new Application(static::$kernel);
$application->add(new CachePoolClearCommand(static::$container->get('cache.global_clearer')));
$application->add(new CachePoolClearCommand(static::getContainer()->get('cache.global_clearer')));
return new CommandTester($application->find('cache:pool:clear'));
}

View File

@ -78,7 +78,7 @@ class CachePoolsTest extends AbstractWebTestCase
private function doTestCachePools($options, $adapterClass)
{
static::bootKernel($options);
$container = static::$container;
$container = static::getContainer();
$pool1 = $container->get('cache.pool1');
$this->assertInstanceOf($adapterClass, $pool1);

View File

@ -27,12 +27,12 @@ class ContainerDebugCommandTest extends AbstractWebTestCase
$application = new Application(static::$kernel);
$application->setAutoExit(false);
@unlink(static::$container->getParameter('debug.container.dump'));
@unlink(static::getContainer()->getParameter('debug.container.dump'));
$tester = new ApplicationTester($application);
$tester->run(['command' => 'debug:container']);
$this->assertFileExists(static::$container->getParameter('debug.container.dump'));
$this->assertFileExists(static::getContainer()->getParameter('debug.container.dump'));
}
public function testNoDebug()
@ -91,7 +91,7 @@ class ContainerDebugCommandTest extends AbstractWebTestCase
$application = new Application(static::$kernel);
$application->setAutoExit(false);
@unlink(static::$container->getParameter('debug.container.dump'));
@unlink(static::getContainer()->getParameter('debug.container.dump'));
$tester = new ApplicationTester($application);
$tester->run(['command' => 'debug:container', '--env-vars' => true], ['decorated' => false]);
@ -128,7 +128,7 @@ TXT
$application = new Application(static::$kernel);
$application->setAutoExit(false);
@unlink(static::$container->getParameter('debug.container.dump'));
@unlink(static::getContainer()->getParameter('debug.container.dump'));
$tester = new ApplicationTester($application);
$tester->run(['command' => 'debug:container', '--env-var' => 'js'], ['decorated' => false]);
@ -156,7 +156,7 @@ TXT
$application = new Application(static::$kernel);
$application->setAutoExit(false);
@unlink(static::$container->getParameter('debug.container.dump'));
@unlink(static::getContainer()->getParameter('debug.container.dump'));
$tester = new ApplicationTester($application);
$tester->run(['command' => 'debug:container', '--deprecations' => true]);
@ -176,7 +176,7 @@ TXT
$application = new Application(static::$kernel);
$application->setAutoExit(false);
@unlink(static::$container->getParameter('debug.container.dump'));
@unlink(static::getContainer()->getParameter('debug.container.dump'));
$tester = new ApplicationTester($application);
$tester->run(['command' => 'debug:container', '--deprecations' => true]);
@ -194,7 +194,7 @@ TXT
$application = new Application(static::$kernel);
$application->setAutoExit(false);
@unlink(static::$container->getParameter('debug.container.dump'));
@unlink(static::getContainer()->getParameter('debug.container.dump'));
$tester = new ApplicationTester($application);
$tester->run(['command' => 'debug:container', '--deprecations' => true]);

View File

@ -20,13 +20,13 @@ class ContainerDumpTest extends AbstractWebTestCase
{
$this->createClient(['test_case' => 'ContainerDump', 'root_config' => 'config.yml']);
$this->assertTrue(static::$container->has('serializer'));
$this->assertTrue(static::getContainer()->has('serializer'));
}
public function testContainerCompilation()
{
$this->createClient(['test_case' => 'ContainerDump', 'root_config' => 'config.yml', 'debug' => false]);
$this->assertTrue(static::$container->has('serializer'));
$this->assertTrue(static::getContainer()->has('serializer'));
}
}

View File

@ -0,0 +1,44 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Bundle\FrameworkBundle\Tests\Functional;
use Symfony\Bundle\FrameworkBundle\Test\TestContainer;
use Symfony\Bundle\FrameworkBundle\Tests\Functional\Bundle\TestBundle\TestServiceContainer\NonPublicService;
use Symfony\Bundle\FrameworkBundle\Tests\Functional\Bundle\TestBundle\TestServiceContainer\PrivateService;
use Symfony\Bundle\FrameworkBundle\Tests\Functional\Bundle\TestBundle\TestServiceContainer\PublicService;
use Symfony\Bundle\FrameworkBundle\Tests\Functional\Bundle\TestBundle\TestServiceContainer\UnusedPrivateService;
use Symfony\Component\DependencyInjection\ContainerInterface;
class KernelTestCaseTest extends AbstractWebTestCase
{
public function testThatPrivateServicesAreUnavailableIfTestConfigIsDisabled()
{
static::bootKernel(['test_case' => 'TestServiceContainer', 'root_config' => 'test_disabled.yml', 'environment' => 'test_disabled']);
$this->expectException(\LogicException::class);
static::getContainer();
}
public function testThatPrivateServicesAreAvailableIfTestConfigIsEnabled()
{
static::bootKernel(['test_case' => 'TestServiceContainer']);
$container = static::getContainer();
$this->assertInstanceOf(ContainerInterface::class, $container);
$this->assertInstanceOf(TestContainer::class, $container);
$this->assertTrue($container->has(PublicService::class));
$this->assertTrue($container->has(NonPublicService::class));
$this->assertTrue($container->has(PrivateService::class));
$this->assertTrue($container->has('private_service'));
$this->assertFalse($container->has(UnusedPrivateService::class));
}
}

View File

@ -28,8 +28,8 @@ class MailerTest extends AbstractWebTestCase
$this->assertEquals('sender@example.org', $envelope->getSender()->getAddress());
};
$eventDispatcher = self::$container->get(EventDispatcherInterface::class);
$logger = self::$container->get('logger');
$eventDispatcher = self::getContainer()->get(EventDispatcherInterface::class);
$logger = self::getContainer()->get('logger');
$testTransport = new class($eventDispatcher, $logger, $onDoSend) extends AbstractTransport {
/**

View File

@ -19,7 +19,7 @@ class PropertyInfoTest extends AbstractWebTestCase
{
static::bootKernel(['test_case' => 'Serializer']);
$this->assertEquals([new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true, new Type(Type::BUILTIN_TYPE_INT), new Type(Type::BUILTIN_TYPE_INT))], static::$container->get('property_info')->getTypes('Symfony\Bundle\FrameworkBundle\Tests\Functional\Dummy', 'codes'));
$this->assertEquals([new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true, new Type(Type::BUILTIN_TYPE_INT), new Type(Type::BUILTIN_TYPE_INT))], static::getContainer()->get('property_info')->getTypes('Symfony\Bundle\FrameworkBundle\Tests\Functional\Dummy', 'codes'));
}
}

View File

@ -20,7 +20,7 @@ class SerializerTest extends AbstractWebTestCase
{
static::bootKernel(['test_case' => 'Serializer']);
$result = static::$container->get('serializer.alias')->deserialize('{"bars": [{"id": 1}, {"id": 2}]}', Foo::class, 'json');
$result = static::getContainer()->get('serializer.alias')->deserialize('{"bars": [{"id": 1}, {"id": 2}]}', Foo::class, 'json');
$bar1 = new Bar();
$bar1->id = 1;

View File

@ -20,6 +20,9 @@ use Symfony\Component\DependencyInjection\ContainerInterface;
class TestServiceContainerTest extends AbstractWebTestCase
{
/**
* @group legacy
*/
public function testThatPrivateServicesAreUnavailableIfTestConfigIsDisabled()
{
static::bootKernel(['test_case' => 'TestServiceContainer', 'root_config' => 'test_disabled.yml', 'environment' => 'test_disabled']);
@ -33,6 +36,9 @@ class TestServiceContainerTest extends AbstractWebTestCase
$this->assertFalse(static::$container->has(UnusedPrivateService::class));
}
/**
* @group legacy
*/
public function testThatPrivateServicesAreAvailableIfTestConfigIsEnabled()
{
static::bootKernel(['test_case' => 'TestServiceContainer']);

View File

@ -21,12 +21,12 @@ class AutowiringTypesTest extends AbstractWebTestCase
{
static::bootKernel(['debug' => false]);
$autowiredServices = static::$container->get('test.autowiring_types.autowired_services');
$autowiredServices = static::getContainer()->get('test.autowiring_types.autowired_services');
$this->assertInstanceOf(AccessDecisionManager::class, $autowiredServices->getAccessDecisionManager(), 'The security.access.decision_manager service should be injected in debug mode');
static::bootKernel(['debug' => true]);
$autowiredServices = static::$container->get('test.autowiring_types.autowired_services');
$autowiredServices = static::getContainer()->get('test.autowiring_types.autowired_services');
$this->assertInstanceOf(TraceableAccessDecisionManager::class, $autowiredServices->getAccessDecisionManager(), 'The debug.security.access.decision_manager service should be injected in non-debug mode');
}

View File

@ -32,10 +32,10 @@ class LoginLinkAuthenticationTest extends AbstractWebTestCase
// we need an active request that is under the firewall to use the linker
$request = Request::create('/get-login-link');
self::$container->get(RequestStack::class)->push($request);
self::getContainer()->get(RequestStack::class)->push($request);
/** @var LoginLinkHandlerInterface $loginLinkHandler */
$loginLinkHandler = self::$container->get(LoginLinkHandlerInterface::class);
$loginLinkHandler = self::getContainer()->get(LoginLinkHandlerInterface::class);
$user = new User('weaverryan', 'foo');
$loginLink = $loginLinkHandler->createLoginLink($user);
$this->assertStringContainsString('user=weaverryan', $loginLink);

View File

@ -51,7 +51,7 @@ class LogoutTest extends AbstractWebTestCase
$client = $this->createClient($options + ['test_case' => 'LogoutWithoutSessionInvalidation', 'root_config' => 'config.yml']);
$client->disableReboot();
$this->callInRequestContext($client, function () {
static::$container->get('security.csrf.token_storage')->setToken('foo', 'bar');
static::getContainer()->get('security.csrf.token_storage')->setToken('foo', 'bar');
});
$client->request('POST', '/login', [
@ -60,14 +60,14 @@ class LogoutTest extends AbstractWebTestCase
]);
$this->callInRequestContext($client, function () {
$this->assertTrue(static::$container->get('security.csrf.token_storage')->hasToken('foo'));
$this->assertSame('bar', static::$container->get('security.csrf.token_storage')->getToken('foo'));
$this->assertTrue(static::getContainer()->get('security.csrf.token_storage')->hasToken('foo'));
$this->assertSame('bar', static::getContainer()->get('security.csrf.token_storage')->getToken('foo'));
});
$client->request('GET', '/logout');
$this->callInRequestContext($client, function () {
$this->assertFalse(static::$container->get('security.csrf.token_storage')->hasToken('foo'));
$this->assertFalse(static::getContainer()->get('security.csrf.token_storage')->hasToken('foo'));
});
}
@ -101,7 +101,7 @@ class LogoutTest extends AbstractWebTestCase
private function callInRequestContext(KernelBrowser $client, callable $callable): void
{
/** @var EventDispatcherInterface $eventDispatcher */
$eventDispatcher = static::$container->get(EventDispatcherInterface::class);
$eventDispatcher = static::getContainer()->get(EventDispatcherInterface::class);
$wrappedCallable = function (RequestEvent $event) use (&$callable) {
$callable();
$event->setResponse(new Response(''));

View File

@ -142,7 +142,7 @@ class SecurityRoutingIntegrationTest extends AbstractWebTestCase
$this->assertEquals(200, $client->getResponse()->getStatusCode(), (string) $client->getResponse());
$this->assertTrue($client->getResponse()->headers->getCacheControlDirective('public'));
$this->assertSame(0, self::$container->get('session')->getUsageIndex());
$this->assertSame(0, self::getContainer()->get('session')->getUsageIndex());
}
private function assertAllowed($client, $path)