Flag of Ukraine
SymfonyCasts stands united with the people of Ukraine
This tutorial has a new version, check it out!

Bootstrapping a Test Suite

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 $12.00

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

Login Subscribe

Our security requirements are about to get... pretty complicated. And so, instead of testing all of that manually and hoping we don't break anything, I think it's time to take a few minutes to get a nice functional testing system set up.

Spin over to your terminal and run:

composer require "test:1.0.6" "symfony/phpunit-bridge:4.3.3" --dev

This will download Symfony's test-pack, which most importantly comes with the PHPUnit bridge: a small Symfony component that wraps around PHPUnit.

When that finishes... yep - we'll put our tests in the tests/ directory and run PHPUnit via php bin/phpunit. That's a bit different than if you installed PHPUnit directly and you'll see why in a minute. That file - bin/phpunit was added by the recipe. And... if you run git status, you'll see that the recipe also added a phpunit.xml.dist file, which holds sensible default config for PHPUnit itself.

Configuring the PHPUnit Version

Open that file up. One of the keys here is called SYMFONY_PHPUNIT_VERSION, which at the time I recorded this is set to 7.5 in the recipe. You can leave this or change it to the latest version of PHPUnit, which for me is 8.2


PHPUnit 8.2 requires PHP 7.2. If you're using PHP 7.1, stay with PHPUnit 7.5.

34 lines phpunit.xml.dist
... lines 1 - 3
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
... lines 5 - 8
<ini name="error_reporting" value="-1" />
<server name="APP_ENV" value="test" force="true" />
<server name="SHELL_VERBOSITY" value="-1" />
<server name="SYMFONY_PHPUNIT_REMOVE" value="" />
<server name="SYMFONY_PHPUNIT_VERSION" value="8.2" />
... lines 17 - 32

But wait... why are we controlling the version of PHPUnit via some variable in an XML file? Isn't PHPUnit a dependency in our composer.json file? Actually... no! When you use Symfony's PHPUnit bridge, you don't require PHPUnit directly. Instead, you tell it which version you want, and it downloads it in the background.

Check it out. Run:

php bin/phpunit

This downloads PHPUnit in the background and installs its dependencies. That's not really an important detail... but it might surprise you the first time you run this. Where did it download PHPUnit? Again, that's not an important detail... but I do like to know what's going on. In your bin/ directory, you'll now find a .phpunit/ directory.

Customizing the test Database

After downloading PHPUnit, that bin/phpunit script does then execute our tests... except that we don't have any yet. Before we write our first one, let's tweak a few other things.

The recipe added another interesting file: .env.test. Thanks to its name, this file will only be loaded in the test environment... which allows us to create test-specific settings. For example, I like to use a different database for my tests so that running them doesn't mess with my development database.

6 lines .env.test
# define your env variables for the test env here
... lines 5 - 6

Inside .env, copy the DATABASE_URL key, paste it in .env.test and add a little _test at the end.

6 lines .env.test
... lines 1 - 4

Cool, right? One of the gotchas of the .env system is that the .env.local file is normally loaded last and allows us to override settings for our local computer. That happens in every environment... except for test. In the test environment, .env & .env.test are read, but not .env.local. That little inconsistency exists so that everyone's test environment behaves the same way.

Anyways, now that our test environment knows to use a different database, let's create that database! Run bin/console doctrine:database:create. But since we want this command to execute in the test environment, also add --env=test:

php bin/console doctrine:database:create --env=test

Repeat that same thing with the doctrine:schema:create command:

php bin/console doctrine:schema:create --env=test

Perfect! Next, Api Platform has some really nice testing tools which... aren't released yet. Boo! Well... because I'm impatient, let's backport those new tools into our app and get our first test running.

Leave a comment!

Login or Register to join the conversation
teh_policer Avatar
teh_policer Avatar teh_policer | posted 3 years ago

BTW. If you install PHPUnit and then change the version to 8.2 and run bin/phpunit again, it will install the new version in another directory with the version postfix.
Happy coding!

1 Reply

Sounds like the behavior I would expect :)

Thijs Avatar

hi there, is there any way to get a repository so I can start from here and up to date? I have many errors and tried to fix them by changing them to different versions but non of them work.. nothing seems to work anymore


Yo Thijs!

Sorry about the trouble - that's not what we want :/. The only code I have available is the same you have. Well, I can fast forward the code to this *exact* chapter, but that's is just the code from the "start" of this tutorial + what we've done in the first 9 chapters. To help, what kinds of issues are you having? Is it related to the API Platform test files that we "backport" from version 2.5 (which wouldn't be necessary when using API Platform 2.5 and later)? Or something different?

Let me know. We run CI on our courses to make sure they keep working - but there are almost definitely "holes" in what we're checking in our CI.




I run out a new issue (dependencies, always dedendencies).

At this point my code is like https://github.com/atournayre/symfonycasts_code_api_platform-_security/commit/f8f5133e0c901d06d044bfba64a17f3246654bc5

When I run
composer require symfony/test-pack --dev

Here is the end of composer's trace
Symfony operations: 1 recipe (07704831784e60d7ba454f35c88fd980)

  • Configuring phpunit/phpunit (>=4.7): From github.com/symfony/recipes:master
    Executing script cache:clear [OK]
    Executing script assets:install public [OK]

Some files may have been created or updated to configure your new packages.
Please review, edit and commit them: these files are yours.

Unpacked symfony/test-pack dependencies
Installing dependencies from lock file (including require-dev)
Verifying lock file contents can be installed on current platform.
Package operations: 0 installs, 0 updates, 1 removal

  • Removing symfony/test-pack (v1.0.8)
    Package zendframework/zend-code is abandoned, you should avoid using it. Use laminas/laminas-code instead.
    Package zendframework/zend-eventmanager is abandoned, you should avoid using it. Use laminas/laminas-eventmanager instead.
    Package phpunit/php-token-stream is abandoned, you should avoid using it. No replacement was suggested.
    28 packages you are using are looking for funding.
    Use the composer fund command to find out more!

start/composer.json do not look like finish/composer.json

In this version of dependencies, php bin/phpunit doesn't work as phpunit do not exists in /bin

After composer require, require-dev looks like this

"require-dev": {
    "phpunit/phpunit": "^9.2",
    "symfony/browser-kit": "^4.3",
    "symfony/css-selector": "^4.3",
    "symfony/maker-bundle": "^1.11",
    "symfony/phpunit-bridge": "^5.3",
    "symfony/profiler-pack": "^1.0"

Exact versions are :
phpunit/phpunit => 9.2.5
symfony/browser-kit => 4.3.11
symfony/css-selector => 4.3.11
symfony/maker-bundle => 1.12.0
symfony/phpunit-bridge => 5.3.3
symfony/profiler-pack => 1.0.4

Do anyone have an idea about how to make phpunit work in this configuration ?


I solve the problem by using code in finish directory


- copy bin/phpunit, composer.json, composer.lock and phpunit.xml.dist from /finish
- composer install
- php bin/phpunit


Hey atournayre

I'm glad you could fix your problem. I believe the recipe that got installed was outdated due to your Symfony version or something else. When I find myself in that situation I just copy-paste the file I'm missing from the recipe repository. If you go to https://flex.symfony.com/ you will find all of the recipes and a link to their repositories


Fernando A. Avatar
Fernando A. Avatar Fernando A. | posted 2 years ago

Ok so I am not sure of what are the advantages of the symfony bridge thing...
As far as I see the only advantage is we have a shortcut to call the tests, other than that it makes reading the test results harder with the amount of spam it fills my console with and makes my CI containers have to download the test suit every time since it is out of composer install step on my build stage.

Either I am doing something wrong or in a less recommended way, or the bridge is not that useful...

So what are the practical advantages of the bridge? What am I doing wrong??

Note: the involuntary spam is always a negative point for me. I should opt in to it not the other way around...


Hey Fernando A.

It's a good question =) First about CI setup, you should save bin/.phpunit/ folder in persistent cache, so it won't be downloaded each time. So now about advantages, the main is that you will have cleaner dependencies and installed phpunit will not conflict any of you installed deps, also it will not block something from installing, also it has a lot of helpers for testing you can find more exact info here https://symfony.com/doc/current/components/phpunit_bridge.html


1 Reply
akincer Avatar
akincer Avatar akincer | posted 2 years ago | edited

Now I'm running into this error when trying to install test.

[UnexpectedValueException]<br />Invalid version string "5.x"

Googling this so far only came up with composer self-update as a possible fix but it didn't help. Any ideas?


Hey Aaron,

Hmm, I'd need to see more information about the error. Try again passing the option -vvv to composer. Also, give it a try clearing composer's cache composer clearcache


akincer Avatar

Hmmm, thought I replied but don't see it here. Was it deleted?

akincer Avatar
akincer Avatar akincer | MolloKhan | posted 2 years ago | edited

Clearing the cache didn't seem to help. Here's the full output after clearing the cache.

`Reading ./composer.json
Loading config file ./composer.json
Checked CA file C:\Users\ack\AppData\Local\Temp\ope1669.tmp: valid
Executing command (C:\Users\ack\PhpstormProjects\API-Platform-Training): git branch --no-color --no-abbrev -v
Executing command (C:\Users\ack\PhpstormProjects\API-Platform-Training): git describe --exact-match --tags
Executing command (CWD): git --version
Executing command (C:\Users\ack\PhpstormProjects\API-Platform-Training): git log --pretty="%H" -n1 HEAD --no-show-signature
Executing command (C:\Users\ack\PhpstormProjects\API-Platform-Training): hg branch
Executing command (C:\Users\ack\PhpstormProjects\API-Platform-Training): fossil branch list
Executing command (C:\Users\ack\PhpstormProjects\API-Platform-Training): fossil tag list
Executing command (C:\Users\ack\PhpstormProjects\API-Platform-Training): svn info --xml
Failed to initialize global composer: Composer could not find the config file: C:/Users/ack/AppData/Roaming/Composer/composer.json
To initialize a project, please create a composer.json file as described in the https://getcomposer.org/ "Getting Started" section
Reading C:\Users\ack\PhpstormProjects\API-Platform-Training/vendor/composer/installed.json
Loading plugin Symfony\Flex\Flex
Downloading https://repo.packagist.org/packages.json
Writing C:/Users/ack/AppData/Local/Composer/repo/https---repo.packagist.org/packages.json into cache
Downloading http://repo.packagist.org/p/provider-2013$97f5d9dda812073c84ecf273acfd5fedffe98708e0803b508efcab91e83965bf.json
Downloading http://repo.packagist.org/p/provider-2014$5182f2d4ecee95d6f0d9f26215a61447a4ad337f4463b12f80e5cc6d3bb07d24.json
Downloading http://repo.packagist.org/p/provider-2015$36e049d4d45dc87b656de56bf89bde32cee2d63fa405c99fac52fec5fa75f8e2.json
Downloading http://repo.packagist.org/p/provider-2016$208eddf0d1e2f55e115caed65c94dce8695a5e3de2eccea9b1284571d2d91e71.json
Downloading http://repo.packagist.org/p/provider-2017$65102f8576a5c8ed6c12be8cafdc01623b5e803cd2a6d99bf383e0edcab6b29d.json
Downloading http://repo.packagist.org/p/provider-2018$f1c4fa3a046d712671217832f02c961549da0500e43bbcc8fdd230750b4aae68.json
Downloading http://repo.packagist.org/p/provider-2019$23dcce68f316bda995b715b574d08e81013520917f41050f6cb0b4df946a1f42.json
Downloading http://repo.packagist.org/p/provider-2020-01$2ec363a4baba72e84759e7ec9215a83f86a3aaf9d545907ca87f86193ed6852b.json
Downloading http://repo.packagist.org/p/provider-2020-04$d3ee8af1a5ea0f01060c75aea9e912ddfaecc5ff0cdd5532bb35bd7271a6dbd4.json
Downloading http://repo.packagist.org/p/provider-2020-07$2e28893c98ae8902efaafaa70bcaa12ddae690753fc7082e139664530fa61541.json
Downloading http://repo.packagist.org/p/provider-archived$238324efe8fb943f822bb7872ce9001ea63c2e345322c09f4a2122a9d272411f.json
Downloading http://repo.packagist.org/p/provider-latest$acfeb9c609494e69d892094c60f939fa6f68c7ed2a7232d993bd46d54e105a75.json
Writing C:/Users/ack/AppData/Local/Composer/repo/https---repo.packagist.org/p-provider-latest.json into cache
Writing C:/Users/ack/AppData/Local/Composer/repo/https---repo.packagist.org/p-provider-archived.json into cache
Writing C:/Users/ack/AppData/Local/Composer/repo/https---repo.packagist.org/p-provider-2020-07.json into cache
Writing C:/Users/ack/AppData/Local/Composer/repo/https---repo.packagist.org/p-provider-2020-04.json into cache
Writing C:/Users/ack/AppData/Local/Composer/repo/https---repo.packagist.org/p-provider-2020-01.json into cache
Writing C:/Users/ack/AppData/Local/Composer/repo/https---repo.packagist.org/p-provider-2019.json into cache
Writing C:/Users/ack/AppData/Local/Composer/repo/https---repo.packagist.org/p-provider-2018.json into cache
Writing C:/Users/ack/AppData/Local/Composer/repo/https---repo.packagist.org/p-provider-2017.json into cache
Writing C:/Users/ack/AppData/Local/Composer/repo/https---repo.packagist.org/p-provider-2016.json into cache
Writing C:/Users/ack/AppData/Local/Composer/repo/https---repo.packagist.org/p-provider-2015.json into cache
Writing C:/Users/ack/AppData/Local/Composer/repo/https---repo.packagist.org/p-provider-2014.json into cache
Writing C:/Users/ack/AppData/Local/Composer/repo/https---repo.packagist.org/p-provider-2013.json into cache
Loading plugin PackageVersions\Installer
Running 1.10.13 (2020-09-09 11:46:34) with PHP 7.4.9 on Windows NT / 10.0
Downloading https://flex.symfony.com/aliases.json
Writing C:/Users/ack/AppData/Local/Composer/repo/https---flex.symfony.com/aliases.json into cache
Downloading https://flex.symfony.com/versions.json
Writing C:/Users/ack/AppData/Local/Composer/repo/https---flex.symfony.com/versions.json into cache
Downloading https://repo.packagist.org/packages.json
Writing C:/Users/ack/AppData/Local/Composer/repo/https---repo.packagist.org/packages.json into cache
Reading C:/Users/ack/AppData/Local/Composer/repo/https---repo.packagist.org/p-provider-2013.json from cache
Reading C:/Users/ack/AppData/Local/Composer/repo/https---repo.packagist.org/p-provider-2014.json from cache
Reading C:/Users/ack/AppData/Local/Composer/repo/https---repo.packagist.org/p-provider-2015.json from cache
Reading C:/Users/ack/AppData/Local/Composer/repo/https---repo.packagist.org/p-provider-2016.json from cache
Reading C:/Users/ack/AppData/Local/Composer/repo/https---repo.packagist.org/p-provider-2017.json from cache
Reading C:/Users/ack/AppData/Local/Composer/repo/https---repo.packagist.org/p-provider-2018.json from cache
Reading C:/Users/ack/AppData/Local/Composer/repo/https---repo.packagist.org/p-provider-2019.json from cache
Reading C:/Users/ack/AppData/Local/Composer/repo/https---repo.packagist.org/p-provider-2020-01.json from cache
Reading C:/Users/ack/AppData/Local/Composer/repo/https---repo.packagist.org/p-provider-2020-04.json from cache
Reading C:/Users/ack/AppData/Local/Composer/repo/https---repo.packagist.org/p-provider-2020-07.json from cache
Reading C:/Users/ack/AppData/Local/Composer/repo/https---repo.packagist.org/p-provider-archived.json from cache
Reading C:/Users/ack/AppData/Local/Composer/repo/https---repo.packagist.org/p-provider-latest.json from cache
Downloading http://repo.packagist.org/p/symfony/test-pack$f4ec73f6f7784cf4b4c02a4abf573eadbad89565446ea82d14e6f9f23ac851cc.json
Writing C:/Users/ack/AppData/Local/Composer/repo/https---repo.packagist.org/provider-symfony$test-pack.json into cache

Invalid version string "5.x"

Exception trace:
() at phar://C:/ProgramData/ComposerSetup/bin/composer.phar/vendor/composer/semver/src/VersionParser.php:185
Composer\Semver\VersionParser->normalize() at C:\Users\ack\PhpstormProjects\API-Platform-Training\vendor\symfony\flex\src\Cache.php:123
Symfony\Flex\Cache->getVersions() at C:\Users\ack\PhpstormProjects\API-Platform-Training\vendor\symfony\flex\src\Cache.php:58
Symfony\Flex\Cache->removeLegacyTags() at C:\Users\ack\PhpstormProjects\API-Platform-Training\vendor\symfony\flex\src\TruncatedComposerRepository.php:41
Symfony\Flex\TruncatedComposerRepository->fetchFile() at phar://C:/ProgramData/ComposerSetup/bin/composer.phar/src/Composer/Repository/ComposerRepository.php:366
Composer\Repository\ComposerRepository->whatProvides() at phar://C:/ProgramData/ComposerSetup/bin/composer.phar/src/Composer/Repository/ComposerRepository.php:140
Composer\Repository\ComposerRepository->findPackage() at phar://C:/ProgramData/ComposerSetup/bin/composer.phar/src/Composer/Repository/RepositoryManager.php:58
Composer\Repository\RepositoryManager->findPackage() at C:\Users\ack\PhpstormProjects\API-Platform-Training\vendor\symfony\flex\src\Unpacker.php:39
Symfony\Flex\Unpacker->unpack() at C:\Users\ack\PhpstormProjects\API-Platform-Training\vendor\symfony\flex\src\Command\RequireCommand.php:51
Symfony\Flex\Command\RequireCommand->execute() at phar://C:/ProgramData/ComposerSetup/bin/composer.phar/vendor/symfony/console/Command/Command.php:245
Symfony\Component\Console\Command\Command->run() at phar://C:/ProgramData/ComposerSetup/bin/composer.phar/vendor/symfony/console/Application.php:835
Symfony\Component\Console\Application->doRunCommand() at phar://C:/ProgramData/ComposerSetup/bin/composer.phar/vendor/symfony/console/Application.php:185
Symfony\Component\Console\Application->doRun() at phar://C:/ProgramData/ComposerSetup/bin/composer.phar/src/Composer/Console/Application.php:281
Composer\Console\Application->doRun() at phar://C:/ProgramData/ComposerSetup/bin/composer.phar/vendor/symfony/console/Application.php:117
Symfony\Component\Console\Application->run() at phar://C:/ProgramData/ComposerSetup/bin/composer.phar/src/Composer/Console/Application.php:113
Composer\Console\Application->run() at phar://C:/ProgramData/ComposerSetup/bin/composer.phar/bin/composer:61
require() at C:\ProgramData\ComposerSetup\bin\composer.phar:24

require [--dev] [--prefer-source] [--prefer-dist] [--fixed] [--no-progress] [--no-suggest] [--no-update] [--no-scripts] [--update-no-dev] [--update-with-dependencies] [--update-with-all-dependencies] [--ignore-platform-reqs] [--prefer-stable] [--prefer-lowest] [--sort-packages] [-o|--optimize-autoloader] [-a|--classmap-authoritative] [--apcu-autoloader] [--unpack] [--] [<packages>]...`


I don't really know what's wrong so I'll tell you a few things you can do

1) Upgrade composer composer selfupgrade
2) Upgrade Symfony Flex composer upgrade symfony/flex
3) Create a new Symfony app and try the command there. It's just to confirm that the problem is not your OS

akincer Avatar

Tested on my Linux machine and no issues so I'm guessing there's a bug somewhere in the Windows executables introduced in a recent update.


Hmm, that's very strange but you may be right. Windows is very tricky to work with. If you feel like so, you could open an issue here https://github.com/symfony/cli that's the official repository for reporting issues related to the Symfony CLI


Default user avatar
Default user avatar Aaron Kincer | MolloKhan | posted 2 years ago

OK, so if I create a brand new 5.x project with just "symfony new test" and then go in the test project to try to composer require a package then it works just fine. It's only if I take these actions that there's an issue:

1. Copy course code into new empty project folder
2. Run composer install
3. Run composer require xyz (any package)

Would that be a symfony or composer issue?


Hey @Aaron!

So, you've stumbled over an issue that's occurred in Symfony as they've been renaming their master branch to 5.x. Here is the issue: https://github.com/symfony/...

Basically, if you're inside a project using Symfony Flex 1.5.2 or lower, Flex will now be broken (there is a workaround in the issue to upgrade Flex). Until Friday morning, THIS code came with a version of Flex lower than 1.5.2 and THAT is why you got the error. Unfortunately, this error was introduced around Wednesday, and we didn't catch it, open that issue and fix it until Friday. Sorry about that!

Anyways, try downloading the fresh code again from this page - it should work because it now has a new symfony/flex version. But if you have any issues, please let us know.


Default user avatar
Default user avatar Aaron Kincer | weaverryan | posted 2 years ago | edited

Hey weaverryan you mean this is an instant where the problem did not exist between the keyboard and chair? I need to print out this thread and frame it.


lol - that was a good one :)


Hey @ Aaron Kincer!

> you mean this is an instant where the problem did not exist between the keyboard and chair

HA! Yep! And if you think you are unique in the problem "often" being between the keyboard and chair, I can tell you personally that you're wrong 😉


akincer Avatar

Looks like I'm not the only one experiencing this. Going to start by reinstalling Symfony CLI to see if it helps. Something has obviously gotten borked along the way.

FYI -- I created a brand new project, copied in course code and ran "composer install" then as soon as I tried to composer require a new package got the error.


akincer Avatar

Uninstalling and reinstalling symfony and composer didn't fix it for me like it did for one person. Something strange is going on.

akincer Avatar
akincer Avatar akincer | MolloKhan | posted 2 years ago | edited

#1 says it's up to date. #2 (and just composer upgrade) is failing with a strange error:

Call to a member function getVersions() on null

I'm guessing something got screwed up somewhere. I'll create a new project and start over.

Gaetano S. Avatar
Gaetano S. Avatar Gaetano S. | posted 3 years ago | edited

I have a problem to create a test database. I use docker and this is my two service of docker-compose:

    image: mysql:5.7
    env_file: .env.local
    container_name: mysql57-apiplat
    restart: on-failure
      - '3506:3306'
        - .docker/data/db:/var/lib/mysql
      - gs_net

    image: mysql:5.7
    env_file: .env.test.local
    container_name: mysql57-test-apiplat
    restart: on-failure
      - '3606:3306'
        - .docker/data/db-test:/var/lib/mysql
      - gs_net

For the first db I have this configuration insde .env and it works fine:


In this chapter I have a .env.test and following the tutorial I have to use DATABASE_URL=mysql://sf5_test:sf5_test@mysql/sf5_test.
<u>PLEASE NOTE</u>: When I run docker-compose, inside .env.local, I get the variables for user, password, db and so on.
I use the command to create the db with --env=test and I expect a message more or less like 'db sf5_test already exists' (<u>PLEASE NOTE</u>: if I try to use the console command without --env=test I get the message 'sf5 exists' and it is normal because I created this db) but I got this message:
SQLSTATE[HY000] [1045]: Access denied for user 'sf5_test'@'' (using password: YES).
I tried to look for a solution on the web but it doesn't work.
Could you help me to understand my error?


Hey Gaetano S.

I think you can simplify your setup by reusing the database container for both environments, you only need to tweak your config. Inside config/packages/test/doctrine.yaml append _test to the doctrine.dbal.url key. Example

        url: '%env(resolve:DATABASE_URL)%_test'

Does it makes sense?


Sung L. Avatar
Sung L. Avatar Sung L. | MolloKhan | posted 2 years ago | edited

I followed your suggestion and files look like this:
// docker-compose.yaml
version: '3.7'

    image: 'postgres:11.6'
        POSTGRES_USER: main
        POSTGRES_DB: main
        -   target: 5432
            published: 5432
            protocol: tcp

// packages/doctrine.yaml
        url: '%env(resolve:DATABASE_URL)%'
        server_version: '11.6'
        auto_generate_proxy_classes: true
        naming_strategy: doctrine.orm.naming_strategy.underscore_number_aware
        auto_mapping: true
                is_bundle: false
                type: annotation
                dir: '%kernel.project_dir%/src/Entity'
                prefix: 'App\Entity'
                alias: App

// packages/test/doctrine.yaml

    url: '%env(resolve:DATABASE_URL)%_test'


When I run symfony console doctrine:database:create --env=test, I got this error:
Could not create database "main" for connection named default
An exception occurred while executing 'CREATE DATABASE "main"':

SQLSTATE[42P04]: Duplicate database: 7 ERROR: database "main" already exists

It doesn't seem like creating main_test database.
Any idea? Thanks!


That's interesting. I believe your Database URL variable is formatted different than I expected. Could you run symfony console debug:container --env-vars and look for the DB env var, I'd like to see how it's formatted (I'm guessing it will contain ?serverVersion at the end)

Sung L. Avatar
Sung L. Avatar Sung L. | MolloKhan | posted 2 years ago | edited

This is what I got from symfony console debug:container --env-vars.

<br /> APP_SECRET n/a "018ab41e394191547a91723137e22d31"<br /> CORS_ALLOW_ORIGIN n/a "^https?://(localhost|127\.0\.0\.1)(:[0-9]+)?$"<br /> DATABASE_URL n/a "postgres://main:main@"<br /> JWT_PASSPHRASE n/a "xUqjziAiTJt4otyiBPPA"<br /> JWT_PUBLIC_KEY n/a "%kernel.project_dir%/config/jwt/public.pem"<br /> JWT_SECRET_KEY n/a "%kernel.project_dir%/config/jwt/private.pem"<br /> VAR_DUMPER_SERVER "" n/a<br />
It doesn't have serverVersion. Is it why not working?

Thank you!


Hey Sung L.!

You are running into a problem with the Docker setup and test databases that we're aware of. Basically, if you use the symfony binary + Docker setup, it's not easy to have a test database. The eventual fix will be for us to allow you to override the doctrine.dbal.dbname in the test config file and have this override the database name specified in the doctrine.dbal.url. Right now, if you have the url option specified, and you try to override just the dbname option in the test environment, the url "wins" (we need to make it possible for the dbname to win). This is actually on my open source TODO list (I've validated the fix with Fabien).

So, in your case, the reason it's not working is that the DATABASE_URL (as you can see) has query parameters on the end of it:


This means that when you do this - url: '%env(resolve:DATABASE_URL)%_test' - it ultimately generates this database url:


See the problem?

For now, I've been creating 2 separate database containers - one for the normal environment and one for the test environment. Try downloading the code from this tutorial - https://symfonycasts.com/screencast/api-platform-extending - and looking at the "start" code - you'll see this system in action.

Let me know if you have any questions - doing this simple thing is currently WAY to hard and we (I) need to fix that!


Gaetano S. Avatar

Thanks for your help. I followed your advise and I used the same container for both env. But I have to use the root access (
DATABASE_URL=mysql://root:root@mysql/sf5) of .env.test. otherwise I would have the same error about access denied.


Hey Gaetano S.!

I'm just catching up here. I was little confused by your original setup - I'm not sure how the env_file: .env.local config was working on Docker. If .env.local specifies DATABASE_URL... does the mysql container use this environment variable at all? I know this is something that Symfony/Docker will read, but I'm not aware (but I could be wrong) of whether or not this is something that the MySQL image actually uses to configure itself. Let me know :).

Generally-speaking, I like Diego's solution. But yea, you would probably need to use the root user in order to talk to both databases, or somehow make sure that there is some user that can access both. But other than that, it's a very simple way to set things up.

If you did use 2 different containers, I don't think you would need each to have a different database name or username, etc. Each container is independent, so each could have the exact same database name, username and password. The only thing you would need to modify in .env.test is that hostname - e.g. DATABASE_URL=mysql-test://sf5:sf5@mysql/sf5.


Gaetano S. Avatar

Well, I use a .env.local file because I don't want to put all Mysql variables (MYSQL_ROOT_PASSWORD, MYSQL_DATABASE, MYSQL_USER ans so on) inside the docker_compose. Then I use here the variable APP_ENV=dev and APP_SECRET. And yes, it does. The service of docker-compose (in this case the mysql image) uses these variables. OK, I will try also two different containers with your solution but before I would like to understand how to fix tests. I saw that you replied about it, I let you know. Thanks again, you are all very awesome.


Hi Gaetano S.!

Ah! I understand - thought you ONLY had DATABASE_URL in .env.local - and I was searching the Internet to see if the MySQL Docker image somehow read this :).

And, ok - let's go debug those tests!


Cristian A. Avatar
Cristian A. Avatar Cristian A. | posted 3 years ago

Hi, I'm jumping in in the middle of this screencast and composer require --dev test doesn't find any packages (trying to setup a dev env first and I want to have tests enabled before moving forward).

I'm guessing it's referring to:
composer require symfony/test-pack


Hey Cristian A.

This shortcuts depends on symfon/flex package probably you can't use test shortcut because flex is outdated or not installed. What is your situation?


Cristian A. Avatar
Cristian A. Avatar Cristian A. | sadikoff | posted 3 years ago

Hey, I though I didn't post this :)

Turned out I was in the incorrect folder. I should have been inside /api, but instead tried to install it in the root. After that it worked as expected.


Ha! No problem!)) Anyways feel free to ask question! We are here to help!

Cheers! Have a great development!

Sung L. Avatar
Sung L. Avatar Sung L. | posted 4 years ago

FYI, you need to have PHP 7.2+ to use PHPUnit 8.2. Also installing phpunit and updating dependencies takes some time. For me, it took more than 10 min.
If you know how to make it faster, please share with us.



Hey Sung L.!

Ah, you're right - I should have made a point of that. We'll add a note! About the updating, that is strange. Internally, the script is basically doing a "composer create-project" on PHPUnit itself (which is sort of like doing a composer update) then, depending on your config, possibly also a few other composer commands. So, it shouldn't be super quick, but it shouldn't take more than 1 minute. Do you also see equally slow times if you run, for example, a composer update on your project?


Sung L. Avatar
Sung L. Avatar Sung L. | weaverryan | posted 4 years ago | edited

First, I had XDebug installed recently and I noticed it makes composer require test --dev command super slow. Waited more than 20 min and still no response so I killed the process. After removing XDebug, installing test pack gets faster, but not as fast/responsive as "npm" install. composer update is fast when I running it. However, updating PHPUnit is still slow.


Hey Sung L.!

Yea, XDebug is a huge problem for Composer - that will definitely kill performance. And Composer will never be as fast/responsible as "npm", unfortunately. Part of that I think is due to how sophisticated its dependency algorithm is, but also I think that algorithm could be improved (but very complex systems take a lot of effort to optimize!).

But the fact that composer update is fast, but updating PHPUnit is is still slow doesn't make sense to me. When you execute the phpunit file, ultimately it is loading vendor/symfony/phpunit-bridge/bin/simple-phpunit.php (https://github.com/symfony/symfony/blob/4.4/src/Symfony/Bridge/PhpUnit/bin/simple-phpunit.php). You can see that it's ultimately just running some composer commands - https://github.com/symfony/symfony/blob/042f5b5a9d580fd09889c30f1894af33caa6d775/src/Symfony/Bridge/PhpUnit/bin/simple-phpunit.php#L118-L136

And, of course, these commands should be running as the same terminal user as normal. It's possible (but unlikely) that the script is using a different PHP binary or Composer executable... you could check by hacking into that file and dumping $COMPOSER and $PHP. But mostly, this is a bit of a mystery...

If you found out anything else, let me know!


Cat in space

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

This tutorial works great for Symfony 5 and API Platform 2.5/2.6.

What PHP libraries does this tutorial use?

// composer.json
    "require": {
        "php": "^7.1.3, <8.0",
        "ext-ctype": "*",
        "ext-iconv": "*",
        "api-platform/core": "^2.1", // v2.4.5
        "composer/package-versions-deprecated": "^1.11", // 1.11.99
        "doctrine/annotations": "^1.0", // 1.13.2
        "doctrine/doctrine-bundle": "^1.6", // 1.11.2
        "doctrine/doctrine-migrations-bundle": "^2.0", // v2.0.0
        "doctrine/orm": "^2.4.5", // v2.7.2
        "nelmio/cors-bundle": "^1.5", // 1.5.6
        "nesbot/carbon": "^2.17", // 2.21.3
        "phpdocumentor/reflection-docblock": "^3.0 || ^4.0", // 4.3.1
        "symfony/asset": "4.3.*", // v4.3.2
        "symfony/console": "4.3.*", // v4.3.2
        "symfony/dotenv": "4.3.*", // v4.3.2
        "symfony/expression-language": "4.3.*", // v4.3.2
        "symfony/flex": "^1.1", // v1.18.7
        "symfony/framework-bundle": "4.3.*", // v4.3.2
        "symfony/http-client": "4.3.*", // v4.3.3
        "symfony/monolog-bundle": "^3.4", // v3.4.0
        "symfony/security-bundle": "4.3.*", // v4.3.2
        "symfony/twig-bundle": "4.3.*", // v4.3.2
        "symfony/validator": "4.3.*", // v4.3.2
        "symfony/webpack-encore-bundle": "^1.6", // v1.6.2
        "symfony/yaml": "4.3.*" // v4.3.2
    "require-dev": {
        "hautelook/alice-bundle": "^2.5", // 2.7.3
        "symfony/browser-kit": "4.3.*", // v4.3.3
        "symfony/css-selector": "4.3.*", // v4.3.3
        "symfony/maker-bundle": "^1.11", // v1.12.0
        "symfony/phpunit-bridge": "^4.3", // v4.3.3
        "symfony/stopwatch": "4.3.*", // v4.3.2
        "symfony/web-profiler-bundle": "4.3.*" // v4.3.2