4

I am trying to create a PHPunit test accessing services from the container in symfony. To do so I call self::bootKernel in setUpBeforeClass. In the first test, the self::$kernel is ok, but the second test self::$kernel is null.

This is a simple test to check it:

<?php

namespace App\Tests;

use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;

class KernelTest extends WebTestCase
{
    public static function setUpBeforeClass(): void
    {
        self::bootKernel();
    }

    public function testMethod1(){
        $this->assertNotNull(self::$kernel);
    }

    public function testMethod2(){
        $this->assertNotNull(self::$kernel);
    }
}

This produces the following output:

$ bin/phpunit tests/KernelTest.php 
PHPUnit 7.5.18 by Sebastian Bergmann and contributors.

Notice: Undefined index: warnings in /app/vendor/phpunit/phpunit/src/TextUI/TestRunner.php on line 334

Warning: Invalid argument supplied for foreach() in /app/vendor/phpunit/phpunit/src/TextUI/TestRunner.php on line 334

Testing App\Tests\KernelTest
.F                                                                  2 / 2 (100%)

Time: 58 ms, Memory: 16.00 MB

There was 1 failure:

1) App\Tests\KernelTest::testMethod2
Failed asserting that null is not null.

/app/tests/KernelTest.php:19

FAILURES!
Tests: 2, Assertions: 2, Failures: 1.

As you can see, the second test fails the assertion.

This is the version that I am running of phpunit:

phpunit/phpunit                     8.5.2      The PHP Unit Testing framework.
symfony/phpunit-bridge              v5.0.2     Symfony PHPUnit Bridge

What I am doing wrong? Should I boot kernel in each test? I would like to boot it only once.

1
  • 1
    I think you should reboot the kernel for each test method. If you want to reuse the kernel, just merge the test methods into one test method (you can use other methods not called test... and just call them in a combined testAll method, of course). the kernel assumes it's clean when it's confronted with a new request, what tests usually test, so it's reasonable to kill the kernel after a test.
    – Jakumi
    Commented Jan 29, 2020 at 13:05

1 Answer 1

2

Just have a look at the definition of the WebTestCase, for example through GitHub: in its tearDown method, the parent tearDown of the KernelTestCase (see GitHub once more) is called, and this forces a shutdown of the kernel. As tearDown is called after each invididual test, booting the kernel once before all other tests does not help.

Symfony's own documentation boots the kernel in setUp (happening right before each individual test case), so that looks reasonable to me.

If you fear performance issues, keep in mind that such integration tests should not be used everywhere. By following the usual testing pyramid, you should have lots of unit tests (testing small parts of your code in isolation), less tests for coupled classes (where you could mock depending parts), and only a few test cases covering the whole system

2
  • Thank you, I will boot up the kernel in setUp then, and be sure as you have said to have as few as tests as possible dealing with kernel.
    – David Rojo
    Commented Jan 29, 2020 at 16:44
  • Have fun testing :) The second part is only a recommendation to be thought of - it's still better to have many integration tests (running the whole stuff using the container and kernel) than having none after all ;)
    – Nico Haase
    Commented Jan 29, 2020 at 16:50

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.