Search code examples
phptestingyii2functional-testingcodeception

How to set a value to $_SERVER['var'] on a functional testing?


I have an action to make an 'autologin' based in a id that the system gets from $_SERVER['AUTH_USER']. In my business server that value is always set for authenticated user. Now, I am trying test my autologin (and so many other things that depends the autologin to work) so I need to set some user to that global (just a string).

What I tryed

$_SERVER['AUTH_USER'] = 'someUser';
$I->amOnPage('some-route'); // this page redirects to autologin action where $_SERVER is used to get the user logged.

But when the action autologin is loaded that value is no more inside $_SERVER global and my test crashes.

What I would like to know

Where or how I can set that global value so that my page could behave normally, reading the value and just going on.

I will appreciate any help. Thank you.


Solution

  • It looks like lack of proper abstraction. You should avoid accessing $_SERVER['AUTH_USER'] directly in your app and do it in at most in one place - in component which will provide abstraction for this. So you should probably extend yii\web\Request and add related method for $_SERVER['AUTH_USER'] abstraction:

    class MyRequest extends \yii\web\Request {
    
        private $_myAuthUser;
    
        public function getMyAuthUser() {
            if ($this->_myAuthUser === null) {
                $this->_myAuthUser = $_SERVER['AUTH_USER'];
            }
    
            return $this->_myAuthUser;
        }
    
        public function setMyAuthUser($value) {
            $this->_myAuthUser = $value;
        }
    }
    

    Use new class in your config:

    return [
        'id' => 'app-web',
        // ...
        'components' => [
            'request' => [
                'class' => MyRequest::class,
            ],
            // ...
        ],
    ];
    

    And use abstraction in your action:

    $authUser = explode('\\', Yii::$app->request->getMyAuthUser())[0];
    

    In your tests you can set value using setter in MyRequest:

     Yii::$app->request->setMyAuthUser('domain\x12345');
    

    Or configure this at config level:

    return [
        'id' => 'app-test',
        // ...
        'components' => [
            'request' => [
                'class' => MyRequest::class,
                'myAuthUser' => 'domain\x12345',
            ],
            // ...
        ],
    ];
    

    UPDATE:

    According to slinstj comments, Codeception may loose state of request component, including myAuthUser value. In that case it may be a good idea to implement getMyAuthUser() and setMyAuthUser() on different component (for example Yii::$app->user) or create separate component for that:

    return [
        'id' => 'app-web',
        // ...
        'components' => [
            'authRequest' => [
                'class' => MyRequest::class,
            ],
            // ...
        ],
    ];