Functional tests inside a standalone Symfony2's bundle

后端 未结 1 627
太阳男子
太阳男子 2021-02-01 06:57

I need to make some functional tests directly in a standalone bundle. I don\'t want to test a controller, just some interaction between real services.

I would like to kn

相关标签:
1条回答
  • 2021-02-01 07:46

    Here is my own solution (I summarize all the process for testing in a standalone bundle):

    1. First, a good bundle has its own composer.json to define its dependencies:

    {
        "name": "my/own-bundle",
        "type": "symfony-bundle",
        "description": "Symfony2 bundle that provides ...",
        "keywords": ["my","own"],
        "license": "MIT",
        "authors": [
            {
                "name": "John Doe",
                "email": "john.doe@omg.wtf"
            }
        ],
        "require": {
            "php": ">=5.3.2",
            "symfony/framework-bundle": ">=2.3"
        },
        "require-dev": {
            "phpunit/phpunit": "3.7.*"
        },
        "autoload": {
            "psr-0": { "My\\OwnBundle": "" }
        },
        "target-dir": "My/OwnBundle",
        "minimum-stability": "dev"
    }
    

    Note the use of the dependency on symfony/framework-bundle which is needed for our tests on services. You certainly can lower the dependencies in specifying your own real dependencies on the symfony core.

    With this file I can process the command (do it) to build the vendor directory of my bundle:

    $ composer update
    

    2. Then, I set my phpunit config file:

    <!-- phpunit.xml.dist -->
    
    <?xml version="1.0" encoding="UTF-8"?>
    
    <phpunit backupGlobals="false"
             backupStaticAttributes="false"
             colors="true"
             convertErrorsToExceptions="true"
             convertNoticesToExceptions="true"
             convertWarningsToExceptions="true"
             processIsolation="false"
             stopOnFailure="false"
             syntaxCheck="false"
             bootstrap="Tests/bootstrap.php"
    >
        <testsuites>
            <testsuite name="MyOwnBundle Test Suite">
                <directory>./Tests/</directory>
            </testsuite>
        </testsuites>
    
        <filter>
            <whitelist>
                <directory>./</directory>
                <exclude>
                    <directory>./Resources</directory>
                    <directory>./Tests</directory>
                    <directory>./vendor</directory>
                </exclude>
            </whitelist>
        </filter>
    </phpunit>
    

    3. Then, I set the php bootstrap for the autoload of the class in my test directory:

    // Tests/bootstrap.php
    
    $file = __DIR__.'/../vendor/autoload.php';
    if (!file_exists($file))
    {
        $file = __DIR__.'/../../../../../../vendor/autoload.php';
        if (!file_exists($file))
            throw new RuntimeException('Install dependencies to run test suite.');
    }
    
    $autoload = require_once $file;
    

    These steps are standard for any test in a standalone bundle.

    4. Now, I want to simulate an application to make some functionnal tests on my services:

    I need a kernel class:

    // Tests/AppKernel.php (you can define it in a subdirectory /Fixtures if you prefer)
    
    use Symfony\Component\HttpKernel\Kernel;
    use Symfony\Component\Config\Loader\LoaderInterface;
    
    class AppKernel extends Kernel
    {
        public function registerBundles()
        {
            $bundles = array();
    
            if (in_array($this->getEnvironment(), array('test'))) {
                $bundles[] = new Symfony\Bundle\FrameworkBundle\FrameworkBundle();
                $bundles[] = new My\OwnBundle\MyOwnBundle();
            }
    
            return $bundles;
        }
    
        public function registerContainerConfiguration(LoaderInterface $loader)
        {
            $loader->load(__DIR__.'/config.yml');
        }
    }
    

    And the corresponding config.yml:

    # Tests/config.yml
    
    framework:
        secret: test
        session:
            storage_id: session.storage.mock_file
    
    my_own:
        test: 2
    

    Here is an example with a mock for the session. Don't forget to specify the correct framework configuration nodes if you want to have access to some services (if you don't specify the node session, you have no service session for instance).

    5. Finally, I can retrieve my services like the following in my test classes:

    // Tests/Functional/Handling/Handler.php
    
    namespace My\OwnBundle\Tests\Functional\Handling;
    
    use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
    
    class HandlerTest extends WebTestCase
    {
        private $handler;
    
        protected function setUp()
        {
            require_once __DIR__.'/../../AppKernel.php';
    
            $kernel = new \AppKernel('test', true);
            $kernel->boot();
            $container = $kernel->getContainer();
            $this->handler = $container->get('my_own.handling.handler');
        }
    
        public function testHandle()
        {
            $this->assert($this->handler->handle());
        }
    }
    
    0 讨论(0)
提交回复
热议问题