14
votes

I have a Symfony2 service that is constructed using a parameter from config.yml using dependency injection. I'm now trying to unit test it and find that the unit test does not have access to the container and therefore the service. So I should built one myself using mock data. It would make sense to me if I could now read the config parameter (going first to config_test.yml then config.yml etc etc) but it appears that isn't possible either. This appears to make unit testing a service cumbersome as I would need to code the initialisation parameters into the test instead of the config files.

If there really is no way to construct a service with parameters from config.yml during a unit test, does anyone know the logic as to why it is a Bad Thing™?

4

4 Answers

8
votes

I found this post, because I needed config parameters in my tests myself. This was the first hit on Google.

However, this is a solution which works. There might be better ones.

<?php

...

require_once(__DIR__ . "/../../../../../app/AppKernel.php");

class MediaImageTest extends WebTestCase
{
    private $_application;
    private $storagePath;

    public function setUp() {  
         $kernel = new \AppKernel('test', true);
         $kernel->boot();
         $this->_application = new \Symfony\Bundle\FrameworkBundle\Console\Application($kernel);
         $this->_application->setAutoExit(false)

         $this->storagePath = $this->_application->getKernel()->getContainer()->getParameter('media_path');
    }

    ...
}

You might look in to this too: Access Symfony 2 container via Unit test? Is a much cleaner solution accessing the kernel within unit tests.

13
votes

This works for me:

class MyServiceTest extends WebTestCase
{
    public function testCookies()
    {
        $client = static::createClient();

        $myParams = $client->getKernel()->getContainer()->getParameter('my_params');
    }
}
3
votes

Unit testing is about testing a class in isolation from other classes. To unit test your service you shouldn't need to read anything from the configuration. Just pass a value in your test. In the end, it could potentially work with other values, right?

Of course if there's some logic/validation around the accepted values, you should probably cover it by tests. Think how you'd do it if you were taking this value from the configuration. You simply wouldn't be able to test the behaviour with different values.

If you want to verify if your application is working correctly (your classes collaborate the way you expect), use functional tests or an acceptance testing tool (like Behat).

0
votes

I'm using Symfony 3.2.2, but I think that this could work also for you.

It's simply a line:

$export_dir = static::$kernel->getContainer()->getParameter('export_dir');