如何通过phpunit上的所有测试保留会话?

时间:2012-02-21 01:30:01

标签: session phpunit

我正在使用phpunit测试Zend Framework上的购物车,结帐,付款流程。我通过向购物车添加产品来测试ShoppingCartControllerShoppingCart模型通过将产品ID存储在Zend会话命名空间中来处理产品添加,然后在另一个测试中我想测试产品是否已添加。相同的ShoppingCart模型从同一个Zend会话命名空间变量中检索添加的产品列表。

添加产品测试看起来像这样并且效果很好,var_dump($_SESSION)已添加到调试并正确显示产品:

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);
}

第二个测试尝试通过询问模型来检索产品,var_dump($_SESSION)在测试开始时已经为空。 会话变量已重置,我想找到保留它们的方法,有人可以帮忙吗?

public function testCanDisplayShoppingCartWidget()  {
    var_dump($_SESSION);
    $this->dispatch($this->getRouteUrl("view_shopping_mini_cart"));
    $this->assertResponseCode('200');
}

3 个答案:

答案 0 :(得分:9)

很抱歉指向错误的方向。以下是a way better way实现此目的,由irha.freenode.net的#phpunit频道的ashawley建议:

<?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

  1. 在函数tearDown()中:将$ _SESSION复制到类属性
  2. 在函数setUp()中:将class属性复制到$ _SESSION
  3. 例如,当您删除函数setUp()和tearDown()方法时,此测试失败:

    <?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'] ); 
        }  
    }
    

    还有一个backupGlobals feature,但它对我不起作用。你应该试一试,也许它适用于稳定的PHPUnit。

答案 1 :(得分:2)

这样做非常难看。正确的方法应该是使用依赖注入。

这意味着更改源代码以直接使用此类而不是会话:

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);
}

其他信息:

答案 2 :(得分:0)

您也可以为PHPUnit测试创建随机会话ID,然后确保在每次进一步调用时在cookie中传递此会话ID。使用Curl,您可以使用WS_EX_TOPMOST选项并将其设置为CURLOPT_COOKIE

'PHPSESSID=thesessionidofyourunittest'

我在this stackoverflow answer中详细解释了一些例子。