Behat / Symfony2Extension

Symfony2 extension for Behat
MIT License
394 stars 106 forks source link

Difference between parameter injection and access to `getContainer` #148

Open jdeniau opened 5 years ago

jdeniau commented 5 years ago

Hi,

I just discover a small difference between access getContainer from the KernelDictionary::getContainer().

If I understand correctly, the kernel is rebooted after each scenario or if we call an http request from symfony framework client.

This mean that all services are reinitialized, and particularly doctrine entity managers.

But's that is not really the recommended way of doing this in Symfony 3+ (private services, autowiring, etc.).

On the other hand, if we do inject doctrine as a parameter in behat.yml like this :

default:
  suites:
    default:
      contexts:
        - Mapado\TicketingBundle\Tests\Context\TransactionContext:             
          - '@doctrine.orm.default_entity_manager'

Then the instance of entity manager is not reinitialized when the kernel is rebooted (and thus the unit of work is not "cleared").

I made a "patch" with a context that clear every unit of work after each step, but it's a bit weird, and other users may have similar bugs.

  1. What is the way you recommend about that ?
  2. Is there something we can do in this bundle to prevent that kind of bug ? (maybe re-initialize every contexts after each scenario / steps ?)
  3. May I help with an implementation or does it have to wait after #128 is resolved ?

Thanks

jdeniau commented 5 years ago

Another possible solution may be to use the kernel.reset tag (SF 3.4+).

julienfalque commented 4 years ago

Just got the same issue. Injecting a Symfony service into a Behat context via a constructor argument is different than retrieving it from the kernel injected via KernelAwareContext::setKernel().

I think this is because the container itself it reset on kernel boot so the test container (test.service_container) is reset as well. This means that retrieving private services from it might return new instances instead of the ones previously retrieved (e.g. when injecting them via contexts' constructor).

LoopKarma commented 4 years ago

@julienfalque it seems I got stuck into the same issue. I have a context with dependency on symfony service. Controller of dependency class called 2 times. Did you manage to create any workaround?

julienfalque commented 4 years ago

I don't remember. I think I switched from one way to retrieve the services to the other.