Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Disable persistentServices on Symfony Kernel reboot #3497

Closed
enricog84 opened this issue Sep 8, 2016 · 5 comments
Closed

Disable persistentServices on Symfony Kernel reboot #3497

enricog84 opened this issue Sep 8, 2016 · 5 comments

Comments

@enricog84
Copy link

What are you trying to achieve?

I have a simple REST api and trying to test default CRUD behaviour.
I am using Symfony 2.8 with the DoctrineExtensions::SoftDeleteable being enabled on the affected Entity. So when I am executing the request for DELETE on the Entity it gets soft deleted, on the next request I disable the doctrine filter for SoftDeleteable on the EntityManager, so I can retrieve the soft deleted entity again and delete it again (which results in a hard delete).
The next test file is doing the same on a different end point/entity.

What do you get instead?

The second test file fails because the doctrine service does not get recreated and therefore the filter on the EntityManager is still disabled.
This happens due to the doctrine and entity manager services are treat as persistent services inside the Codeception\Module\Symfony and Codeception\Lib\Connector\Symfony classes.
Removing the part where the stored persistentServices replace the ones from the rebooted container inside Codeception\Lib\Connector\Symfony::rebootKernel would solve the issue for me.

class Symfony extends \Symfony\Component\HttpKernel\Client
{
....
    /**
     * Reboot kernel
     *
     * Services from the list of persistent services
     * are updated from service container before kernel shutdown
     * and injected into newly initialized container after kernel boot.
     */
    public function rebootKernel()
    {

        if ($this->container) {
            foreach ($this->persistentServices as $serviceName => $service) {
                if ($this->container->has($serviceName)) {
                    $this->persistentServices[$serviceName] = $this->container->get($serviceName);
                }
            }
        }

        $this->kernel->shutdown();
        $this->kernel->boot();
        $this->container = $this->kernel->getContainer();

        if ($this->container->has('profiler')) {
            $this->container->get('profiler')->enable();
        }

        #NOTE: Do not replace rebooted services
//        foreach ($this->persistentServices as $serviceName => $service) {
//            $this->container->set($serviceName, $service);
//        }
    }

So why are there persistent services in the first place? Shouldn't the request being execute as isolated as possible? Could a new configuration option be implemented that we are able to disabled the usage of persistentServices?

Details

  • Codeception version: 2.2.4 (happens since >=2.1.8)
  • Symfony version: 2.8.11
  • PHP Version: 5.5.9
  • Operating System: Ubuntu
  • Installation type: Composer
  • List of installed packages (composer show)
  • Suite configuration:

global codeception.yml

paths:
    tests: tests
    log: tests/_log
    data: tests/_data
    helpers: tests/_helpers
settings:
    bootstrap: _bootstrap.php
    colors: true
    memory_limit: -1
    log: true
modules:
    config:
        Db:
            dsn: 'mysql:host=localhost;dbname=wmtest_symfony'
            user: 'root'
            password: 'xxxxx'
            dump: tests/_data/dump.sql
        PhpBrowser:
            url: 'http://127.0.0.1:80/app_test.php'
        REST:
            depends: Symfony
        Symfony:
            app_path: 'app'
            environment: 'test'
            debug: false
            rebootable_client: true
            debug: true
            part: SERVICES
        Doctrine2:
            depends: Symfony
groups:
    # add 2 tests to db group
    testGroup: [tests/api/auth/rolesCept.php, tests/api/auth/customersCept.php]
coverage:
    enabled: true
    include:
        - src/*.php
    exclude:

#api.suite.yml
class_name: ApiGuy
modules:
    enabled: 
        - Db
        - Doctrine2
        - ApiHelper
        - REST
        - Asserts

api.suite.yml

class_name: ApiGuy
modules:
    enabled: 
        - Db
        - Doctrine2
        - ApiHelper
        - REST
        - Asserts
@Naktibalda
Copy link
Member

So why are there persistent services in the first place?

Because Doctrine2 module wraps a whole test in transaction and rolls back in _after to restore the initial state.

All services were persisted between requests before rebootKernel was introduced.
Persistent service functionality keeps Doctrine module working.

If you want more isolation, use a Db module of Codeception.

@enricog84
Copy link
Author

Ok, tough on versions < 2.1.8 the persistentServices were not taken over to the next test file within the Symfony module, only between requests inside one test file.
So this is now the expected behaviour?

Besides that I found a solution to my problem by letting the REST module depend on PhpBrowser instead of Symfony.

@Naktibalda
Copy link
Member

You have too many modules enabled - you should have only one of PhpBrowser and Symfony and one of Doctrine2 and Db.

It is no longer allowed to have PhpBrowser and Symfony enabled in the same suite in Codeception 2.2

@enricog84
Copy link
Author

Yes I only had one of Symfony or PhpBrowser enabled as dependency via REST module.
Will have a look at Db vs Doctrine.
Thanks for your help so far.

@enricog84
Copy link
Author

Was now able to test it. After removing the Doctrine2 module the tests also succeed when run together.

So the following combination of enabled modules worked for me:

  • REST (depending on Symfony)
  • Symfony
  • Db

Tough because there where no conflicts with the combination of modules I thought they could be used together. I did use Doctrine2s grabFromRepository method (did now replace them by Symfony services) and Db modules cleanup/populate functioniality. Maybe there should be a notice on the docs if this is not recommend.

So this was only a configuration issue and can be closed.
Thanks for your time.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants