Codeception / module-yii2

Codeception module for Yii2 framework
MIT License
16 stars 36 forks source link

[Yii2 module] request headers always empty #52

Closed Patrick-Remy closed 2 years ago

Patrick-Remy commented 2 years ago

What are you trying to achieve?

Multiple requests in single test with different Headers.

What do you get instead?

Always empty headers inside a Yii2 controller.


        $this->tester->haveHttpHeader('Authorization', '42');
        $this->tester->sendGet('/foo');
        $this->tester->haveHttpHeader('Authorization', 'bar');
        $this->tester->sendGet('/foo');
        // FooController will see empty Header collection when checking Yii::$app->request->headers

Details

Before sending a request, the Yii Module clears the headers in that way $request->getHeaders()->removeAll(); https://github.com/Codeception/module-yii2/blob/7befe4789dbed651cac5693a2464da21cd0de14f/src/Codeception/Lib/Connector/Yii2.php#L577-L578

Unfortunately Yii's getRequest() method internally caches the headers in a private property. Therefore on multiple requests the headers are always an empty collection, as the getter won't check again the ENVs. Reference: https://github.com/yiisoft/yii2/blob/df6e5869bd856d76750423385b69e4bc66c6ffa6/framework/web/Request.php#L360-L391

If I use a custom Request class in the tests, that do not cache at all, it works as expected. Setting requestCleanMethod: 'recreate' int he api.suite.yml does not help in my case, as I have behaviors attached to the Request, so it will get reset to self::CLEAN_CLEAR.

SamMousa commented 2 years ago

Why not set it to force recreate? The message indicates that is the proper course if action, assuming behaviours are attached in config

SamMousa commented 2 years ago

Also going back to your code sample... Just put those requests in different tests... You get a fresh application object, way cleaner.

Patrick-Remy commented 2 years ago

As a workaround, force_recreate works as well as my mock, that's right, but either way for me the it seem's to be a bug. Probably haveHeader() and deleteHeader() should also update the HeaderCollection?

SamMousa commented 2 years ago

It's not a bug in the module. The issue is that Yii2 as a framework is meant to handle 1 request per instance (since that is how PHP works in most modes). So we try to work around that, and succeed in 99% of the cases.

SamMousa commented 2 years ago

So we try to warn you if your case might be the 1%, so you can figure out what's needed to resolve it. Have header and delete header don't reach into components, that would be very dangerous. The component is an encapsulation boundary we should not cross.

The functions you mentioned btw don't do anything but prepare the request that has not yet been send; this happens outside the framework, only when you call sendRequest it is passed on.

Apologies for lack of mark-up, am on phone.