【问题标题】:Using PHPUnit to test cookies and sessions, how?使用 PHPUnit 测试 cookie 和会话,如何?
【发布时间】:2011-03-04 06:28:27
【问题描述】:

使用 PHPUnit 可以很容易地测试原始 PHP 代码,但是严重依赖 cookie 的代码呢?会话可能是一个很好的例子。

是否有不需要我在测试期间使用数据设置$_COOKIE 的方法?这感觉像是一种 hacky 的做事方式。

【问题讨论】:

  • 你能详细说明一下hacky吗?你能在测试的setUp 中只使用unset($_COOKIE) 吗?
  • 我真的不想在我的测试中处理这个问题。我觉得这是不必要的混乱,应该自动处理。

标签: php unit-testing session cookies phpunit


【解决方案1】:

这是代码的常见问题,尤其是过时的 PHP 代码。常用的技术是进一步抽象相关对象中的 COOKIE/SESSION 变量,并使用控制反转技术将这些依赖关系拉入范围。

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

现在在执行测试之前,您将实例化 Cookie/Session 对象的模拟版本并提供默认数据。

我想,通过在执行测试之前简单地覆盖超级全局值,可以使用遗留代码实现相同的效果。

干杯, 亚历克斯

【讨论】:

    【解决方案2】:

    我知道这已经很老了,但我相信这需要更新,因为自原始帖子以来技术已经改进。我能够使用 php 5.4 和 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());
        }
    }
    

    【讨论】:

    • 进一步调查使我(在我看来)正确实现了输出缓冲作为注释:@outputBuffering enabled 将其放在函数的 cmets 中,它会处理缓冲问题。
    【解决方案3】:

    我发现我可以使用 PHPUnit 来测试我的网站中严重依赖会话的部分的行为,通过 Curl 和一个通过的 cookie 的组合会话 ID

    以下Curl 类使用CURLOPT_COOKIE 选项传递会话参数。静态变量$sessionid 保存不同Curl 调用之间的会话。此外,可以使用静态函数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();
        }
    }
    

    一个示例调用

    $data = array(
        'action' => 'someaction',
        'info' => 'someinfo'
    );
    
    $curl = new Curl(
        'http://localhost/somephp.php', 
        array(
            CURLOPT_POSTFIELDS => http_build_query($data)));
    
    $response = $curl->getResponse();
    

    并且任何后续的 Curl 调用都将自动使用与前一个相同的会话,除非专门调用了 Curl::changeSession()

    【讨论】:

      猜你喜欢
      • 2014-02-24
      • 2011-02-28
      • 2015-11-24
      • 2010-11-26
      • 2013-11-06
      • 2017-11-10
      • 2012-03-11
      • 1970-01-01
      • 2011-03-23
      相关资源
      最近更新 更多