如何在使用phpunit进行测试时生成会话变量

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何在使用phpunit进行测试时生成会话变量相关的知识,希望对你有一定的参考价值。

在使用phpUnit测试一段代码(按照codeigniter mvc编写)时,我得到了错误PHP致命错误:在非对象上调用成员函数getPermissionObject()。

代码如下所示,产生错误的部分缩进。

class Some_model extends Model 
{
    var $userid;
    var $permisson_object;
    var $username;
    var $userType;
    var $userFirstName;

    function Some_model()
    {
        parent::Model();
        $user_obj = @unserialize($this->db_session->userdata('user_object')); 

           //following line shows error
           $this->permisson_object = $user_obj->getPermissionObject();

        $this->userid = $user_obj->getUserid();
        $this->username = $user_obj->getUsername();
        $this->userType =$user_obj->getusertype();
        $this->userFirstName = $user_obj->getFirstName()." ".$user_obj->getLastName();
    }
}

出现错误是因为在测试时我无法从我的测试类生成$ user_obj(因为它是从会话数据生成的)。

我的要求是在测试类中生成相同的内容,以便我可以使用它。

谢谢


感谢您的回复。

该对象看起来像这样:

User_library Object
(
    [username:User_library:private] => staff@some.com
    [firstname:User_library:private] => some
    [lastname:User_library:private] => Staff
    [typename:User_library:private] => 
    [userid:User_library:private] => 2
    [userType:User_library:private] => 2
    [permissionObject:User_library:private] => Permission_library Object
        (
            [create_custom_attr:Permission_library:private] => 1
            [create_jobspecific_attr:Permission_library:private] => 0
            [injob:Permission_library:private] => Array
                (
                    [products] => 2
                    [services] => 2
                    [options] => 2
                    [tasks_assigned_to_me] => 2
                    [tasks_assigned_to_others] => 2
                )

            [outjob:Permission_library:private] => Array
                (
                    [products] => 2
                    [services] => 2
                    [options] => 2
                    [tasks_assigned_to_others] => 2
                )

            [samedept:Permission_library:private] => Array
                (
                )

            [alldepts:Permission_library:private] => Array
                (
                    [add_and_assign_tasks] => 4
                    [add_and_assign_milestones] => 4
                )

        )

我找不到任何模拟这个的选项,因为这个对象中还有其他对象。这里User_library Object是类User_library的对象。这里面也有Permission_library对象。我怎样才能通过以下方式模仿上述内容:

$observer = $this->getMock('Some_model', array('Some_model'));

$observer->expects($this->any())
                 ->method('Some_model')
                 ->with($this->equalTo('something'));

在这里我的问题是在$this->equalTo('something')的某些部分会有什么?

答案

你的问题的一个可能的答案是"Dependency Injection",坦率地说,我最喜欢的那个。只是简单的嘲笑也是可能的。

一些例子

<?php 
// You could pass the session into the object while constructing it
// so in your test you can pass in a "fake" user object (see below)
class Some_model extends Model {
function Some_model($user_object) {
    $user_object->yourFunctions();
}

这样你就不必依赖某些全球状态的设置正确的方式。

如果这对你不起作用(我不知道codeigniter真的很好),你可以像这样:

<?php 
class Some_model extends Model {
function Some_model($user_object=null) {
    if($user_obj === null) {
        $user_obj = @unserialize($this->db_session->userdata('user_object')); 
    }
    $user_object->yourFunctions();
}

因此,在您的测试中,您传入一个模拟的用户对象(您创建的假实例,对于mocking see the docs),您的普通代码不必更改。

也很好读:Slides about PHPUnit best practices from the PHPUnit Author。希望帮助澄清我试图解释的:)

编辑

sidhartha要求对模拟提供一些帮助,所以我写了一些更多的演示代码。我已经删除了大部分内容以提供完整的可执行示例,因为我猜“你可以运行的代码”比其他任何东西都更有帮助。

假设这是您要测试的代码(缩减为用户ID,因此它更短)

<?php
class Some_model extends Model 
{

    var $userid;
    var $permisson_object;

    function Some_model()
    {
        parent::Model();
        $user_obj = @unserialize($this->db_session->userdata('user_object')); 
        //following line shows error
        $this->permisson_object = $user_obj->getPermissionObject();
        $this->userid = $user_obj->getUserid();
     }

 }

使用我试图解释的你可以构建一个像这样的测试(一个文件中的所有内容都可以复制粘贴eaiser,当然有人会将其拆分)

class Model { public function Model() {}  }

class Some_model extends Model
{

    var $userid;
    var $permisson_object;

    function Some_model($user_obj)
    {
        parent::Model();
        //following line shows error
        $this->userid = $user_obj->getUserid();
        $this->permisson_object = $user_obj->getPermissionObject();
     }

    public function getThatUserid() {
        // Just to show off how mocking works a little bit better :)
        return $this->userid;
    }

}

class Permissions {
    public function getPermissions() {
        // lots of code here maybe
        return array("something from" => "the database");
    }
}

class User {
    public function getUserid() {
        // code code
        return 1;
    }
    public function getPermissionObject() {

    }
}



class Some_modelTest extends PHPUnit_Framework_Testcase {

    public function testConstruction() {
        $mockUser = $this->getMock("User");
        $mockPermissions = $this->getMock("Permission");

        $mockUser->expects($this->once())
                 ->method("getUserid")
                 ->will($this->returnValue(100));
#        $mockPermissions->expects($this->once())
#                        ->method("getPermissions");

        // Now for the "magic"
        $mockUser->expects($this->once())
                 ->method("getPermissionObject")
                 ->will($this->returnValue($mockPermissions));
         // ^^ now we are all set and user_obj is independen of the permissons object
        // Now pass the "Fake" user into the model
        $model = new Some_model($mockUser);
        // and just to show off the "will return value stuff"
        $this->assertSame(100, $model->getThatUserid());
    }
}

phpunit由Sebastian Bergmann撰写的Some_modelTest.php PHPUnit 3.4.15。

.

时间:0秒,内存:4.25Mb

好的(1个测试,3个断言)

我真的希望有所帮助。这是很多代码,但作为演示它应该适合你。

以上是关于如何在使用phpunit进行测试时生成会话变量的主要内容,如果未能解决你的问题,请参考以下文章

在单独的进程中运行测试时,PHPUnit 无法生成代码覆盖率

无法发送会话 cookie - 标头已发送 PHPUnit / Laravel

PHPUnit - 使用 $_POST 变量测试 MVC 控制器

当我使用标志覆盖率运行 Phpunit 时,出现错误:未定义的变量工厂

PHPUnit - 转储变量

我如何在超过 1 个网站上执行 phpunit 测试