Reputation: 367
I'm working on testing a shopping cart, checkout, payment process on Zend Framework with phpunit. I'm testing ShoppingCartController
by adding products to cart, a ShoppingCart
Model handles product additions by storing product id's in a Zend Session Namespace, and then in another test I want to test that the products were added. The same ShoppingCart
Model retrieves a list of added products from the same Zend Session namespace variable.
The add product test looks like this and works well, and the var_dump($_SESSION)
was added to debug and shows the products correctly:
public function testCanAddProductsToShoppingCart() {
$testProducts = array(
array(
"product_id" => "1",
"product_quantity" => "5"
),
array(
"product_id" => "1",
"product_quantity" => "3"
),
array(
"product_id" => "2",
"product_quantity" => "1"
)
);
Ecommerce_Model_Shoppingcart::clean();
foreach ($testProducts as $product) {
$this->request->setMethod('POST')
->setPost(array(
'product_id' => $product["product_id"],
'quantity' => $product["product_quantity"]
));
$this->dispatch($this->getRouteUrl("add_to_shopping_cart"));
$this->assertResponseCode('200');
}
$products = Ecommerce_Model_Shoppingcart::getData();
$this->assertTrue($products[2][0]["product"] instanceof Ecommerce_Model_Product);
$this->assertEquals($products[2][0]["quantity"],
"8");
$this->assertTrue($products[2][1]["product"] instanceof Ecommerce_Model_Product);
$this->assertEquals($products[2][1]["quantity"],
"1");
var_dump($_SESSION);
}
The second test attempts to retrieve the products by asking the model to do so, the var_dump($_SESSION)
is null already at the beginning of the test. The session variables were reset, I want to find a way to preserve them, can anyone help?
public function testCanDisplayShoppingCartWidget() {
var_dump($_SESSION);
$this->dispatch($this->getRouteUrl("view_shopping_mini_cart"));
$this->assertResponseCode('200');
}
Upvotes: 12
Views: 15016
Reputation: 634
You can also just create a random session id for your PHPUnit test, and then make sure you pass this session id in a cookie in every further call you make. With Curl, you would use the CURLOPT_COOKIE
option and set it to 'PHPSESSID=thesessionidofyourunittest'
as such:
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_COOKIE, 'PHPSESSID=thesessionidofyourunittest');
I explained more in detail and with an example in this stackoverflow answer.
Upvotes: 0
Reputation: 33420
Sorry for pointing you in the wrong direction. Here is a way better way of achieving this, suggested by ashawley from #phpunit channel of irc.freenode.net:
<?php
# running from the cli doesn't set $_SESSION here on phpunit trunk
if ( !isset( $_SESSION ) ) $_SESSION = array( );
class FooTest extends PHPUnit_Framework_TestCase {
protected $backupGlobalsBlacklist = array( '_SESSION' );
public function testOne( ) {
$_SESSION['foo'] = 'bar';
}
public function testTwo( ) {
$this->assertEquals( 'bar', $_SESSION['foo'] );
}
}
?>
== END UPDATE
For example, this test fails when you remove the functions setUp() and tearDown() methods:
<?php
# Usage: save this to test.php and run phpunit test.php
# running from the cli doesn't set $_SESSION here on phpunit trunk
if ( !isset( $_SESSION ) ) $_SESSION = array( );
class FooTest extends PHPUnit_Framework_TestCase {
public static $shared_session = array( );
public function setUp() {
$_SESSION = FooTest::$shared_session;
}
public function tearDown() {
FooTest::$shared_session = $_SESSION;
}
public function testOne( ) {
$_SESSION['foo'] = 'bar';
}
public function testTwo( ) {
$this->assertEquals( 'bar', $_SESSION['foo'] );
}
}
Also there is a backupGlobals feature but it doesn't work for me. You should try it thought, maybe it works on stable PHPUnit.
Upvotes: 11
Reputation: 5718
that's a very ugly of doing that. The right way should be using dependency injection.
That implies changing your source code to use this class instead of sessions directly:
class Session
{
private $adapter;
public static function init(SessionAdapter $adapter)
{
self::$adapter = $adapter;
}
public static function get($var)
{
return self::$adapter->get($var);
}
public static function set($var, $value)
{
return self::$adapter->set($var, $value);
}
}
interface SessionAdapter
{
public function get($var);
public function set($var, $value);
}
Additional information:
Upvotes: 3