开发者

Using PHPUnit to test cookies and sessions, how?

With PHPUnit it's quite easy to test raw PHP code, but what about code that heavily relies on cookies? Sessions 开发者_Go百科could be a good example.

Is there a method that doesn't require me to setup $_COOKIE with data during my test? It feels like a hacky way of doing things.


This is a common problem with code, especially lagacy PHP code. The common technique used is to further abstract the COOKIE/SESSION variables in related objects and using inversion of control technique(s) to pull those dependencies into scope.

http://martinfowler.com/articles/injection.html

Now before you execute a test you would instantiate a mock version of a Cookie/Session object and provide default data.

I imagine, the same effect can be achieved with legacy code by simply overriding the super global value before executing the test.

Cheers, Alex


I understand this is quite old, but I believe this needs to be updated as technology has improved since the original post. I was able to get sessions working with this solution using php 5.4 with phpunit 3.7:

class UserTest extends \PHPUnit_Framework_TestCase {
    //....
    public function __construct () {
        ob_start();
    }

    protected function setUp() {
       $this->object = new \User();
    }

    public function testUserLogin() {
       $this->object->setUsername('test');
       $this->object->setPassword('testpw');
       // sets the session within:
       $this->assertEquals(true, $this->object->login());
    }
}


I found that I could use PHPUnit to test the behavior of the part of my website that relies heavily on sessions, through a combination of Curl and a cookie that passes the session id.

The following Curl class uses the CURLOPT_COOKIE option to pass a session parameter. The static variable $sessionid saves the session between different Curl calls. Further, sessions can be changed using the static function changeSession.

class Curl {
    private $ch;
    private static $sessionid;

    public function __construct($url, $options) {
        $this->ch = curl_init($url);

        if (!self::$sessionid)
            self::$sessionid = .. generateRandomString() ..;

        $options = $options + array(
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_COOKIE => 'PHPSESSID=' . self::$sessionid);

        foreach ($options as $key => $val) {
            curl_setopt($this->ch, $key, $val);
        }
    }

    public function getResponse() {
        if ($this->response) {
            return $this->response;
        }

        $response = curl_exec($this->ch);
        $error    = curl_error($this->ch);
        $errno    = curl_errno($this->ch);
        $header_size = curl_getinfo($this->ch, CURLINFO_HEADER_SIZE);
        $this->header = substr($response, 0, $header_size);
        $response = substr($response, $header_size);

        if (is_resource($this->ch)) {
            curl_close($this->ch);
        }

        if (0 !== $errno) {
            throw new \RuntimeException($error, $errno);
        }

        return $this->response = $response;
    }

    public function __toString() {
        return $this->getResponse();
    }

    public static function changeSession() {
        self::$SESSIONID = Practicalia::generateRandomString();
    }
}

An example call

$data = array(
    'action' => 'someaction',
    'info' => 'someinfo'
);

$curl = new Curl(
    'http://localhost/somephp.php', 
    array(
        CURLOPT_POSTFIELDS => http_build_query($data)));

$response = $curl->getResponse();

And any subsequent Curl calls will automatically use the same session as the previous one, unless specifically Curl::changeSession() is called.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜