【问题标题】:How to preserve session through all tests on phpunit?如何通过 phpunit 上的所有测试保留会话?
【发布时间】:2012-03-11 08:55:36
【问题描述】:

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

添加产品测试看起来像这样并且运行良好,并且添加了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');
}

【问题讨论】:

    标签: session phpunit


    【解决方案1】:

    很抱歉为您指明了错误的方向。这是实现这一目标的a way better way,由 irc.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'] );
        }
    
    }
    
    ?>
    

    == 结束更新

    1. 在函数 tearDown() 中:将 $_SESSION 复制到类属性并
    2. 在函数setUp()中:复制class属性到$_SESSION

    例如,当您删除函数 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。

    【讨论】:

    • 您建议在测试用例之间分享会话吗??
    • 您可以创建一个扩展 PHPUnit_Framework_TestCase 的 SharedSessionTestCase,并在那里定义 $shared_session、setUp() 和 tearDown()。然后,您可以拥有几个扩展 SharedSessionTestCase 的测试用例。
    • 我添加了一个更好的答案。
    • 好的,再次感谢,.. 我会尝试新方法,并且肯定会尝试扩展 PHPUnit_Framework_TestCase
    • 当然,这就是为什么我把最初的帖子留在原地,这可能会有所帮助......我们都会学习,这样即使对您的客户来说也是双赢的 B)
    【解决方案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);
    }
    

    附加信息:

    【讨论】:

      【解决方案3】:

      您也可以为您的 PHPUnit 测试创建一个随机会话 id,然后确保在您进行的每次进一步调用中将此会话 id 传递到 cookie 中。使用 Curl,您可以使用 CURLOPT_COOKIE 选项并将其设置为 'PHPSESSID=thesessionidofyourunittest',如下所示:

      $ch = curl_init($url);
      curl_setopt($ch, CURLOPT_COOKIE, 'PHPSESSID=thesessionidofyourunittest');
      

      我在this stackoverflow answer 中以示例进行了更详细的解释。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-03-04
        • 2010-11-30
        • 1970-01-01
        • 2017-12-05
        • 2020-04-28
        • 2010-11-27
        • 2018-05-19
        • 1970-01-01
        相关资源
        最近更新 更多