Functional/Integration tests for standalone symfony bundles
Introduction
When your are working in a new bundle to share with other projects sometimes you create new service in your bundle with infrastructure dependencies (doctrine, redis, mysql, rabbitMQ, file system …) or include controllers.
In some cases we want to test real behaviour without mocking the dependencies (integration/functional tests) to check if our services are working fine with real dependencies and symfony container.
So to can do functional/integration tests in standalone using the symfony container in our bundle we can add symfony kernel
in our Tests
folder, we will add FrameworkBundle
and own bundle to simulate integration bundle in the final symfony application.
Usage
Create AppKernel.php
file inside of Tests
folder and add the next code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
<?php
namespace Tests;
use BernardoSecades\FunctionalTestBundle\FunctionalTestBundle;
use Symfony\Bundle\FrameworkBundle\FrameworkBundle;
use Symfony\Component\Config\Loader\LoaderInterface;
use Symfony\Component\HttpKernel\Kernel;
class AppKernel extends Kernel
{
/**
* @return array
*/
public function registerBundles()
{
$bundles = array();
if (in_array($this->getEnvironment(), array('test'))) {
$bundles[] = new FrameworkBundle();
$bundles[] = new NameBundleWeAreWorkingBundle();
}
return $bundles;
}
/**
* @param LoaderInterface $loader
*/
public function registerContainerConfiguration(LoaderInterface $loader)
{
$loader->load(__DIR__.'/config_'.$this->getEnvironment().'.yml');
}
/**
* {@inheritdoc}
*/
public function getCacheDir()
{
return sys_get_temp_dir().'/NameBundleWeAreWorkingBundle/cache';
}
/**
* {@inheritdoc}
*/
public function getLogDir()
{
return sys_get_temp_dir().'/NameBundleWeAreWorkingBundle/logs';
}
}
Create the file config_test.yml
with next lines to load your services in test environment:
1
2
3
4
5
6
imports:
- { resource: "@NameBundleWeAreWorkingBundle/Resources/config/services.yml" }
framework:
secret: "Three can keep a secret, if two of them are dead."
test: ~
This configuration will be loaded by AppKernel.php
we added before. Check this piece of code from
kernel file:
1
2
3
4
5
6
7
8
9
10
11
12
<?php
// ...
/**
* @param LoaderInterface $loader
*/
public function registerContainerConfiguration(LoaderInterface $loader)
{
$loader->load(__DIR__.'/config_'.$this->getEnvironment().'.yml');
}
And now you can load the class AppKernel
in your test putting like first parameter
the environment, in this case, environment test
:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
<?php
namespace Tests\Functional;
use Tests\AppKernel;
use BernardoSecades\NameBundleWeAreWorkingBundle\Lib\MyService;
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
use Symfony\Component\DependencyInjection\ContainerInterface;
class MyTest extends KernelTestCase
{
/** @var ContainerInterface */
protected $container;
protected function setUp()
{
parent::setUp();
$kernel = new AppKernel('test', true);
$kernel->boot();
$this->container = $kernel->getContainer();
}
/**
* @test
*/
public function checkMyService()
{
$myService = $this->container->get('bernardosecades.my_service');
$this->assertInstanceOf(MyService::class, $myService);
$this->assertTrue($myService->myAction());
}
}
See the example in github, functional-tests-standalone-bundle.