Flag of Ukraine
SymfonyCasts stands united with the people of Ukraine

Controller Functional Test

Keep on Learning!

If you liked what you've learned so far, dive in!
Subscribe to get access to this tutorial plus
video, code and script downloads.

Start your All-Access Pass
Buy just this tutorial for $8.00

With a Subscription, click any sentence in the script to jump to that part of the video!

Login Subscribe

We just added a route and controller, and since this bundle is going to be used by, probably, billions of people, I want to make sure they work! How? By writing a good old-fashioned functional test that surfs to the new URL and checks the result.

In the tests/ directory, create a new Controller directory and a new PHP class inside called IpsumApiControllerTest. As always, make this extend TestCase from PHPUnit, and add a public function testIndex().

... lines 1 - 10
class IpsumApiControllerTest extends TestCase
{
public function testIndex()
{
}
}

How to Boot a Fake App?

The setup for a functional test is pretty similar to an integration test: create a custom test kernel, but this time, import routes.xml inside. Then, we can use Symfony's BrowserKit to make requests into that kernel and check that we get a 200 status code back.

Start by stealing the testing kernel from the FunctionalTest class. Paste this at the bottom, and, just to avoid confusion, give it a different name: KnpULoremIpsumControllerKernel. Re-type the l and hit tab to add the use statement for the Kernel class.

... lines 1 - 18
class KnpULoremIpsumControllerKernel extends Kernel
{
public function __construct()
{
parent::__construct('test', true);
}
public function registerBundles()
{
return [
new KnpULoremIpsumBundle(),
];
}
public function registerContainerConfiguration(LoaderInterface $loader)
{
$loader->load(function(ContainerBuilder $container) {
});
}
public function getCacheDir()
{
return __DIR__.'/../cache/'.spl_object_hash($this);
}
}

Then, we can simplify: we don't need any special configuration: just call the parent constructor. Re-type the bundle name and hit tab to get the use statement, and do this on the other two highlighted classes below. Empty the load() callback for now.

Yep, we're just booting a kernel with one bundle... super boring.

Do we Need FrameworkBundle Now?

And here's where things get confusing. In composer.json, as you know, we do not have a dependency on symfony/framework-bundle. But now... we have a route and controller... and... well... the entire routing and controller system comes from FrameworkBundle! In other words, while not impossible, it's incredibly unlikely that someone will want to import our route, but not use FrameworkBundle.

This means that we now depend on FrameworkBundle. Well actually, that's not entirely true. Our new route & controller are optional features. So, in a perfect world, FrameworkBundle should still be an optional dependency. In other words, we are not going to add it to the require key. In reality, if you did, no big deal - but we're doing things the harder, more interesting way.

This leaves us with a big ugly problem! In order to test that the route and controller work, we need the route & controller system! We need FrameworkBundle! This is yet another case when we need a dependency, but we only need the dependency when we're developing the bundle or running tests. Find your terminal and run:

composer require symfony/framework-bundle --dev

Let this download. Excellent!

Importing Routes from the Kernel

Back in the test, thanks to FrameworkBundle, we can use a really cool trait to make life simpler. Full disclosure, I helped created the trait - so of course I think it's cool. But really, it makes life easier: use MicroKernelTrait. Remove registerContainerConfiguration() and, instead go back again to the Code -> Generate menu - or Command + N on a Mac - and implement the two missing methods: configureContainer(), and configureRoutes().

Tip

Starting in Symfony 5.1, the first argument to configureRoutes() should be RoutingConfigurator $routes.

... lines 1 - 20
class KnpULoremIpsumControllerKernel extends Kernel
{
use MicroKernelTrait;
... lines 24 - 36
protected function configureRoutes(RouteCollectionBuilder $routes)
{
}
... line 41
protected function configureContainer(ContainerBuilder $c, LoaderInterface $loader)
{
}
... lines 46 - 50
}

Cool! So... let's import our route! $routes->import(), then the path to that file: __DIR__.'/../../src/Resources/config/routes.xml'.

Tip

If you're using the RoutingConfigurator $routes argument to configureRoutes() (Symfony 5.1 and later), then import with:

$routes->import(__DIR__.'/../../src/Resources/config/routes.xml')->prefix('/api');

... lines 1 - 36
protected function configureRoutes(RouteCollectionBuilder $routes)
{
$routes->import(__DIR__.'/../../src/Resources/config/routes.xml', '/api');
}
... lines 41 - 51

Setting up the Test Client

Nice! And... that's really all the kernel needs. Back up in testIndex(), create the new kernel: new KnpULoremIpsumControllerKernel().

... lines 1 - 13
class IpsumApiControllerTest extends TestCase
{
public function testIndex()
{
$kernel = new KnpULoremIpsumControllerKernel();
... lines 19 - 23
}
}
... lines 26 - 57

Now, you can almost pretend like this a normal functional test in a normal Symfony app. Create a test client: $client = new Client() - the one from FrameworkBundle - and pass it the $kernel.

Tip

In Symfony 4.3 and higher, use KernelBrowser instead of Client: the class was renamed.

Use this to make requests into the app with $client->request(). You will not get auto-completion for this method - we'll find out why soon. Make a GET request, and for the URL... actually, down in configureRoutes(), ah, I forgot to add a prefix! Add /api as the second argument. Make the request to /api/.

... lines 1 - 15
public function testIndex()
{
... line 18
$client = new Client($kernel);
$client->request('GET', '/api/');
... lines 21 - 23
}
... lines 25 - 57

... lines 1 - 26
class KnpULoremIpsumControllerKernel extends Kernel
{
... lines 29 - 42
protected function configureRoutes(RouteCollectionBuilder $routes)
{
$routes->import(__DIR__.'/../../src/Resources/config/routes.xml', '/api');
}
... lines 47 - 56
}

Cool! Let's dump the response to see what it looks like: var_dump($client->getResponse()->getContent()). Then add an assert that 200 matches $client->getResponse()->getStatusCode().

... lines 1 - 13
class IpsumApiControllerTest extends TestCase
{
public function testIndex()
{
... lines 18 - 21
var_dump($client->getResponse()->getContent());
$this->assertSame(200, $client->getResponse()->getStatusCode());
}
}
... lines 26 - 57

Alright! Let's give this a try! Find your terminal, and run those tests!

./vendor/bin/simple-phpunit

Woh! They are not happy:

Fatal error class BrowserKit\Client does not exist.

Hmm. This comes from the http-kernel\Client class. Here's what's happening: we use the Client class from FrameworkBundle, that extends Client from http-kernel, and that tries to use a class from a component called browser-kit, which is an optional dependency of http-kernel. Geez.

Basically, we're trying to use a class from a library that we don't have installed. You know the drill, find your terminal and run:

composer require "symfony/browser-kit:^4.0" --dev

When that finishes, try the test again!

./vendor/bin/simple-phpunit

Oof. It just looks awful:

LogicException: Container extension "framework" is not registered.

This comes from ContainerBuilder, which is called from somewhere inside MicroKernelTrait. This is a bit tougher to track down. When we use MicroKernelTrait, behind the scenes, it adds some framework configuration to the container in order to configure the router. But... our kernel does not enable FrameworkBundle!

No problem: add new FrameworkBundle to our bundles array.

... lines 1 - 35
public function registerBundles()
{
return [
... line 39
new FrameworkBundle(),
];
}
... lines 43 - 60

Then, go back and try the tests again: hold your breath:

./vendor/bin/simple-phpunit

No! Hmm:

The service url_signer has a dependency on a non-existent parameter "kernel.secret".

This is a fancy way of saying that, for some reason, there is a missing parameter. It turns out that FrameworkBundle has one required piece of configuration. In your application, open config/packages/framework.yaml. Yep, right on top: the secret key.

This is used in various places for security, and, since it needs to be unique and secret, Symfony can't give you a default value. For our testing kernel, it's meaningless, but it needs to exist. In configureContainer(), add $c->loadFromExtension() passing it framework and an array with secret set to anything. The FrameworkExtension uses this value to set that missing parameter.

Tip

In Symfony 5.1, to avoid a deprecation warning, you'll also need to set a router key with utf8: true:

'secret' => 'F00',
'router' => ['utf8' => true],

... lines 1 - 48
protected function configureContainer(ContainerBuilder $c, LoaderInterface $loader)
{
$c->loadFromExtension('framework', [
'secret' => 'F00',
]);
}
... lines 55 - 60

Do those tests... one, last time:

./vendor/bin/simple-phpunit

Phew! They pass! The response status code is 200 and you can even see the JSON. Go back to the test and take out the var_dump().

Next, let's get away from tests and talk about events: the best way to allow users to hook into your controller logic.

Leave a comment!

34
Login or Register to join the conversation
Michael B. Avatar
Michael B. Avatar Michael B. | posted 1 year ago

Hey Ryan!!!

I ask myself if it is possible to register routes automaticly. I mean, I would register controllers and routes from inside my bundles without the need to let the users import the route manually. The configureRoutes method is not an option since I can not change the kernel of the app of my bundle users, isn't it?

Thanks!

Reply

Hey Michael,

I'm not sure if it is possible :) And probably it's done due to security reasons. Well, Symfony create recipes exactly for this reasons, to help users to do less routing work. So, basically, you just need to create a recipe and Symfony Flex will automatically copy your import file for routes to their project. You can push a recipe for your bundle to this repo: https://github.com/symfony/... :)

I hope this helps!

Cheers!

1 Reply
Bruno D. Avatar
Bruno D. Avatar Bruno D. | posted 1 year ago

Hello weaverryan .
As the configureRoutes signature is not the same for symfony 5.0 and for higher versions, is there a way to make this code valid for all symfony 5 versions ?

Reply

Hey Bruno,

Thank you for your interest in SymfonyCasts tutorials!

Yes, since Symfony 5.1 the first argument to configureRoutes() should be "RoutingConfigurator $routes". Unfortunately, we cannot update the code in our tutorials because we want the code we show in videos matches the exact code from course downloads. But we can add notes to existent tutorials, and we added one about this configureRoutes(). I hope this helps!

In the future, we will consider to re-record the tutorial on a newer version of Symfony, but for now it's not a high priority for this course unfortunately, so we don't have any plans doing this soon.

Also, we do recommend our users to download the course code and code along with us instead of coding on the latest version of Symfony, basically because our course code already have some modifications before we start the course. If you download the course code and run composer install - this should not be a problem for you. But if you run composer update instead - you should be ready to do some tweaks in the code according to the upgrade docs.

I hope all this will help you to follow our courses. And as always, if you have any questions or if you stuck following our courses on a newer version of Symfony and don't know how to move further - please, let us know in the comments and we will help!

Cheers!

Reply
Bruno D. Avatar

Hey Victor Bocharsky

Thank you for your response.

My need behind this question is really to find a way to do a functional test for a bundle that I am making that is compatible for all versions of symfony 5 (not just doing this course).
So I think an appropriate solution to this problem would be to check the kernel version and use a dynamically created Anonymous class to instantiate the custom kernel. Something like this:

if (\Symfony\Component\HttpKernel\Kernel::VERSION >= "5.1") {
$customKernel = new class() extends Kernel {
protected function configureRoutes(RoutingConfigurator $routes)
{
$routes->import(__DIR__.'/../../src/Resources/config/routes.xml');
}
};
} else {
$customKernel = new class() extends Kernel {
protected function configureRoutes(RouteCollectionBuilder $routes)
{
}
};
}

What do you tkink about it ? It may help someone else who has this need.

Reply

Hey Bruno,

Yeah, that's the valid way when you need to maintain some legacy versions like in this case, just check for Kernel version as you do in your example, or sometimes you may want to check for PHP version to write a bit different PHP code for legacy PHP versions you still have to support.

Also, it's a good idea to trigger a deprecation notice in legacy code so that your users start seeing the deprecations and plan an upgrade soon. This way you may control the legacy code and get rid of them in some time. For example, if you want to drop Symfony 5.0 support in new major version of your bundle, you trigger the deprecation notice now saying that Symfony 5.0 support will be dropped soon and after some time when you release a new major version of it - you clean all the deprecation code.

Just a few tips that may help :)

Cheers!

Reply
triemli Avatar
triemli Avatar triemli | posted 2 years ago

I think in configureRoutes method should be *RoutingConfigurator $routes* instead of *RouteCollectionBuilder $routes*
Then
$routes->import(__DIR__.'/../../src/Resources/config/routes.xml', '/api');

'/api' should we remove? But now we have request URI trouble:

Uncaught PHP Exception Symfony\Component\HttpKernel\Exception\NotFoundHttpException: "No route found for "GET /api/"" at /mnt/d/domains/FactorioBundle/vendor/symfony/http-kernel/EventListener/RouterListener.php line 136

So and additional deprecation error on test execute:

1x: Since symfony/framework-bundle 5.1: Not setting the "framework.router.utf8" configuration option is deprecated, it will default to "true" in version 6.0.
Reply

Hey WebAdequate!

Sorry for the slow reply!

> I think in configureRoutes method should be *RoutingConfigurator $routes* instead of *RouteCollectionBuilder $routes*

Yep! You're right! That changed in Symfony 5.1 :). I'll add a note about this!

> '/api' should we remove? But now we have request URI trouble:

As soon as you use RouteCollectionBuilder, this line will need to change to:


$routes->import(__DIR__.'/../../src/Resources/config/routes.xml')->prefix('/api');

I'll add a note about that too. If you have any issues, let me know :).

> 1x: Since symfony/framework-bundle 5.1: Not setting the "framework.router.utf8" configuration option is deprecated, it will default to "true" in version 6.0.

That's obviously another change in 5.1 :). You now need to set this setting to true (or false, I think it won't matter for us) inside configureContainer(). We'll add a note here too.

Phew! Thanks for the comment - this kind of highlights the job of a bundle maintainer - there is a constant stream of small tweaks to keep your bundle up to date with Symfony.

Cheers!

Reply
triemli Avatar

Thanks a lot! It works!

fix framework.router.utf8 error:


protected function configureContainer(ContainerBuilder $builder): void
{
$builder->loadFromExtension('framework', [
'secret' => 'asdqwe',
'router' => [
'utf8' => true
]
]);
}

In routes.xml also need to use double :: in controller=api_controller::actionIndex"

Reply

Bah! Thanks for that fix - I just updated it - routing -> router.

> In routes.xml also need to use double :: in controller=api_controller::actionIndex"

We *do* have a note about that already in the previous chapter when we add the routes.xml file https://symfonycasts.com/sc... :)

Cheers!

Reply
Damien millet Avatar
Damien millet Avatar Damien millet | posted 2 years ago

HI, the locale isn't same in app and in bundle, why ? how can i change this ?

Reply

Hey Damien.Millet !

How are you fetching the locale? These *should* be the same - the locale is a, sort of, "global" value that is set on the request (*how* it's set can be done in a number of different ways) and then accessible via $request->getLocale(). Let me know what you're seeing :).

Cheers!

Reply
Damien millet Avatar
Damien millet Avatar Damien millet | weaverryan | posted 2 years ago

i use $request->getLocale() :/

Reply

Hey Damien.Millet!

Perfect! So you said:

> the locale isn't same in app and in bundle

What are you seeing that makes you think this? There is only 1 Request object during a request - regardless of if you're running code inside a bundle or inside your app code. So the locale should be the same. It's possible that something is *changing* the locale between when one part of code (e.g. app code) runs and the other code (e.g. bundle code) runs. Another edge-case possibility is that, if you're using a sub-request, then the locale could be different inside the subrequest (a sub request most normally happens when using the Twig render() function).

Cheers!

Reply
Damien millet Avatar
Damien millet Avatar Damien millet | weaverryan | posted 2 years ago

when i use a controller for does a $request->getLocale() i get fr, but when i try to call a method who return $request->getLocale() i get en

Reply

Hey Damien.Millet!

If you dump the value in both places, which is dumped first? Is it "fr" and then "en" or the opposite? And which value are you expecting (which is correct)? The "fr" locale? Are you using (as far as you know) any sub requests?

Cheers!

Reply
Sergey Avatar

1. While running test on Symfony 4.4 I'm getting a warning:


Remaining indirect deprecation notices (1)

1x: Auto-injection of the container for "knpu_lorem_ipsum.ipsum_api_controller" is deprecated since Symfony 4.2. Configure it as a service instead.
1x in IpsumApiControllerTest::testIndex from KnpU\LoremIpsumBundle\Tests\Controller

And I really can't figure out what should I do to get rid of it.

Cause I have already registered as a service in 'services.xml'


<service id="knpu_lorem_ipsum.ipsum_api_controller" class="KnpU\LoremIpsumBundle\Controller\IpsumApiController" public="true">
<argument type="service" id="knpu_lorem_ipsum.knpu_ipsum"/>
</service>

And bundle is loading:


public function registerBundles()
{
return [
new KnpULoremIpsumBundle(),
new FrameworkBundle(),
];
}

What exactly should I do?

2. I'm feeling my self pretty unsure with all these tricks with Kernel in Test

What should I study to feel more confident?

Reply

Hey Сергей Боборыкин !

Interesting! And sorry for my late reply :). So yes, this is tricky. Let me explain what (should be) the fix... then a bit more about how I figured that out.

The missing piece - I believe - is that your controller service needs a container.service_subscriber tag:


<service id="knpu_lorem_ipsum.ipsum_api_controller" class="KnpU\LoremIpsumBundle\Controller\IpsumApiController" public="true">
<tag name="container.service_subscriber"/>
<argument type="service" id="knpu_lorem_ipsum.knpu_ipsum"/>
</service>

So why does that fix things? First, I Google'd the deprecation message because I wanted to find the GitHub issue where it was introduced: https://github.com/symfony/...

The CHANGELOG addition gives us the best hint:

> Deprecated auto-injection of the container in AbstractController instances, register them as service subscribers instead

So, AbstractController gets access to a container, but it's not the MAIN container, it's actually a mini-container - via a service subscriber. We talk about service subscribers here - https://symfonycasts.com/sc... - and will also talk about AbstractController *specifically* in a few days on our Deep Dive tutorial - https://symfonycasts.com/sc... - it will be part of the "controller resolver" chapters.

So it would appear that your controller was not "registered as a service subscriber". Normally, to be a service subscriber, you must implement ServiceSubscriberInterface on your controller class and... you're done! AbstractController implements this... so just by extending it, your controller is implementing it. So, what's the problem? In reality, if you want your service to be a "service subscriber", you need to implement that interface AND tag your service with container.service_subscriber. In normal application code, we don't need to manually add that tag because "autoconfigure" takes care of it for us: Symfony automatically adds that tag when it sees that our controller service implements the interface.

However, in "bundle land", we don't use autowiring or autoconfiguration (to keep things explicit). And so, it's up to *you* to add this tag :).

> 2. I'm feeling my self pretty unsure with all these tricks with Kernel in Test
> What should I study to feel more confident?

First, I'd say - don't feel too bad. This is *pretty* advanced stuff :). But, we will (hopefully in about 1 month) release a "Deep Dive into Symfony's Container" course as part 2 of our Deep Dive series (the first tutorial - https://symfonycasts.com/sc... - is all about the request-response process). In that 2nd part, we'll be talking about the Kernel, configuration, how the container is built, service subscribers, etc, etc. I think going through both of those courses when they're available will definitely help. But mostly, feel good that you're even *trying* this stuff - the world of "coding a reusable bundle" is totally strange, complex and different than "app" development :).

Cheers!

1 Reply
Sergey Avatar

Hi there @weaverryan!

Thanks a lot for such a comprehensive answer!
Really!!! :)

Unfortunately it did't work out for me.

I have added the tag just as you suggested:


<service id="knpu_lorem_ipsum.ipsum_api_controller" class="KnpU\LoremIpsumBundle\Controller\IpsumApiController" public="true">
<tag name="container.service_subscriber"/>
<argument type="service" id="knpu_lorem_ipsum.knpu_ipsum"/>
<argument type="service" id="event_dispatcher" on-invalid="null"/>
</service>

And I see it in the definition at extesion loading:


// \KnpU\LoremIpsumBundle\DependencyInjection\KnpULoremIpsumExtension

public function load(array $configs, ContainerBuilder $container)
{
$loader = new XmlFileLoader($container, new FileLocator(__DIR__ . '/../Resources/config'));
$loader->load('services.xml');

$controller = $container->getDefinition('knpu_lorem_ipsum.ipsum_api_controller');

var_dump($controller->getTags()); exit;

// ...
}


Output:
array(1) {
'container.service_subscriber' =>
array(1) {
[0] =>
array(0) {
}
}
}

But still I'm getting the warning:

1x: Auto-injection of the container for "knpu_lorem_ipsum.ipsum_api_controller" is deprecated since Symfony 4.2. Configure it as a service instead.
1x in IpsumApiControllerTest::testIndex from KnpU\LoremIpsumBundle\Tests\Controller
Reply

Hey Сергей Боборыкин !

And thanks for the detailed reply :). After some research, here is the detail I think I missed. Try adding a "call" to your service for "setContainer":


<service id="knpu_lorem_ipsum.ipsum_api_controller" class="KnpU\LoremIpsumBundle\Controller\IpsumApiController" public="true">
<call method="setContainer">
<argument type="service" id="Psr\Container\ContainerInterface"/>
</call>
<tag name="container.service_subscriber"/>
<argument type="service" id="knpu_lorem_ipsum.knpu_ipsum"/>
<argument type="service" id="event_dispatcher" on-invalid="null"/>
</service>

I rely on autowiring magic so often, that I forget sometimes what I need to do. So, in order for the service subscriber to work, your service (of course) needs to have the tag. But it *also* needs an argument (or an argument to a "call") to be the service Psr\Container\ContainerInterface. When the service subscriber system sees that argument, it knows that it should replace it with the service locator (instead of passing you the real container). Normally, a controller is autowired and this call is configured *for* you because AbstractController has a setContainer() method with this type-hint AND that method has an @required above it, which tells the autowiring system to add a call for it.

Phew! Let me know if it works. Fascinating, deep, dark stuff ;)

Cheers!

3 Reply
Default user avatar

adding `<call>` to the configuration also appears to fix a "container not set" problem that appears in Symfony 5 when you move your controllers in chapter 13. That being said, I was given an example of a bundle that supposedly works with Symfony 5 and their controllers don't appear to require the use of `<call>`: https://github.com/willdura...

I haven't tested this bundle myself, for the record.

Edit:
------
In a possibly unrelated matter, for this chapter I run into:
> Error: Class 'Symfony\Bundle\FrameworkBundle\Client' not found

Reply

Hey ash-m!

> adding `<call>` to the configuration also appears to fix a "container not set" problem that appears in Symfony 5 when you move your controllers in chapter 13

Perfect! 👍

> That being said, I was given an example of a bundle that supposedly works with Symfony 5 and their controllers don't appear to require the use of `<call>`: https://github.com/willdura...

I see it! The difference is that their controller - https://github.com/willdura... - doesn't extend AbstractController. It's AbstractController where the special functionality is needed to add the "call" (that's because this class implements ServiceSubscriberInterface - if you choose not to use the base class, then you have no need to inject the mini-container and life is good).

> In a possibly unrelated matter, for this chapter I run into:
> Error: Class 'Symfony\Bundle\FrameworkBundle\Client' not found

I think it's unrelated... but related to Symfony 4 vs 5. This class doesn't exist in Symfony 5 - it was deprecated in Symfony 4 - https://github.com/symfony/... - the KernelBrowser is this class - https://github.com/symfony/...

I'll add a note about that to the tutorial to help Symfony 5 users :).

Cheers!

1 Reply
Default user avatar

Thanks, I tried to look this up myself but there are several issues that sort of reference each other and I wasn't sure how to apply it to the project. It helps a lot to just know that the implementation is basically the same using the KernelBrowser class.

Reply

Hey ash-m!

Haha, yea... all the changes and backwards compatibility layers and libraries depending on various versions of other libraries, believe me, it can get complex! Thanks again for bringing this up!

Cheers!

Reply
Default user avatar
Default user avatar Patrick | posted 3 years ago

HI there,
First of all thanks for the great tutorial, I'm learning a lot on how to create a bindle in symfony 4(.2)

When I try to run the test mentioned in this article, I get the following error:

Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException: You have requested a non-existent service "http_kernel".

If I trace it back it comes down to the following linea in symfony/http-kernel/kernell.php


/**
* Gets a HTTP kernel from the container.
*
* @return HttpKernel
*/
protected function getHttpKernel()
{
return $this->container->get('http_kernel');
}




What did I do wrong?

Reply
MichalWilczynski Avatar
MichalWilczynski Avatar MichalWilczynski | Patrick | posted 3 years ago

Hi, I had the same error and I managed that typo in class extended TestCase, line $kernel = new ClassWithTypo causing this problem.

Reply
Default user avatar

Somehow I managed to bypass this issue. (I made a typo somehwere?)

The only problem now I'm facing is that, despite of me adding the secret via the configureContainer-function inn my kernell-class, I keep receiving the error that it has not been set.

I've already tried with adding a config folder, but this failed aswell.

I'm going to do some more digging...

Reply

Hey Patrick,

Hm, it sounds like a misprint, I even not sure that it might be a cache problem. Anyway, I'm glad you bypass this error.

Cheers!

Reply
Default user avatar

Moving the declaration of the secret to the registerContainerConfiguration-function did the trick. Now struging with the routes not being correct. I will fix that aswell!

Reply

Hey Patrick!

You're on a roll man! Keep it up! ;) Let us know if you have any problems you can't resolve yourself.

Cheers!

Reply
Default user avatar
Default user avatar Lucas Baldassari | posted 4 years ago

One of my services (event_listener.controller) has a dependency '@doctrine'. How can I get this service available in my tests?

Reply

Hey Lucas Baldassari

It depends on which Symfony version you are using. If you are using Symfony 4.1, then you should be able to just fetch it from the container, but not for the normal container, there is another one only available when testing. Check this out: https://symfony.com/blog/ne...

Cheers!

Reply
Default user avatar
Default user avatar Lucas Baldassari | MolloKhan | posted 4 years ago

Thanks for your answer! But in WebTestCase or even KernelTestCase, container does not have doctrine service, what is indicating that I need to register DoctrineBundle, right? But where do I register the Doctrine bundle and load its configuration if I'm using the KernelTestCase, that encapsulate the Kernel creation? I think the only way is to implement a TestKernel, like in the video, but in the registerBundles I add new DoctrineBundle(), and in the configureContainer() I load the doctrine configuration. It's ok or I'm doing something wrong from the point of view of best practices?

Reply

Hey Lucas Baldassari

Sorry for the late replay. If your test class extends from "KernelTestCase" or "WebTestCase", you should be able to get Doctrine from the container, but you have to boot the kernel first. Maybe this example can help you figuring it out: https://symfony.com/doc/cur...

Cheers!

Reply
Cat in space

"Houston: no signs of life"
Start the conversation!

This tutorial is built using Symfony 4, but most of the concepts apply fine to Symfony 5!

What PHP libraries does this tutorial use?

// composer.json
{
    "require": {
        "php": "^7.1.3",
        "ext-iconv": "*",
        "doctrine/annotations": "^1.8", // v1.8.0
        "knplabs/knp-markdown-bundle": "^1.7", // 1.7.0
        "knpuniversity/lorem-ipsum-bundle": "*@dev", // dev-master
        "nexylan/slack-bundle": "^2.0,<2.2", // v2.0.1
        "php-http/guzzle6-adapter": "^1.1", // v1.1.1
        "sensio/framework-extra-bundle": "^5.1", // v5.1.6
        "symfony/asset": "^4.0", // v4.0.6
        "symfony/console": "^4.0", // v4.0.6
        "symfony/flex": "^1.0", // v1.18.7
        "symfony/framework-bundle": "^4.0", // v4.0.6
        "symfony/lts": "^4@dev", // dev-master
        "symfony/twig-bundle": "^4.0", // v4.0.6
        "symfony/web-server-bundle": "^4.0", // v4.0.6
        "symfony/yaml": "^4.0", // v4.0.6
        "weaverryan_test/lorem-ipsum-bundle": "^1.0" // v1.0.0
    },
    "require-dev": {
        "easycorp/easy-log-handler": "^1.0.2", // v1.0.4
        "sensiolabs/security-checker": "^4.1", // v4.1.8
        "symfony/debug-bundle": "^3.3|^4.0", // v4.0.6
        "symfony/dotenv": "^4.0", // v4.0.6
        "symfony/maker-bundle": "^1.0", // v1.1.1
        "symfony/monolog-bundle": "^3.0", // v3.2.0
        "symfony/phpunit-bridge": "^3.3|^4.0", // v4.3.3
        "symfony/stopwatch": "^3.3|^4.0", // v4.0.6
        "symfony/var-dumper": "^3.3|^4.0", // v4.0.6
        "symfony/web-profiler-bundle": "^3.3|^4.0" // v4.0.6
    }
}