问题
With PHPUnit it's quite easy to test raw PHP code, but what about code that heavily relies on cookies? Sessions 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.
回答1:
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
回答2:
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());
}
}
回答3:
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.
来源:https://stackoverflow.com/questions/3050137/using-phpunit-to-test-cookies-and-sessions-how