Во время тестирования фрагмента кода (написанного в соответствии с codeigniter mvc) с помощью PHPUnit я получил ошибку Неустранимая ошибка 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 из моего тестового класса (так как он генерируется из сессии data).
Мое требование - создать то же самое в тестовом классе, чтобы я мог его использовать.
Спасибо
Спасибо за ваш ответ.
Объект выглядит примерно так:
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 ('thing ')
?
Один из возможных ответов на вашу проблему - «Внедрение зависимостей»
, честно говоря, тот, который мне нравится больше всего. Также возможно простое издевательство.
В некоторых примерах
<?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();
}
поэтому в ваших тестах вы передаете имитированный пользовательский объект (созданный вами фальшивый экземпляр, для насмешливых см. документацию ), и ваш обычный код не должен меняться.
Также полезно прочитать: Слайды о лучших практиках PHPUnit от автора PHPUnit . Надеюсь, эта помощь проясняет то, что я пытался объяснить :)
sidhartha попросил некоторую помощь с издевательством, поэтому я написал еще немного демонстрационного кода.Я вырезал большинство вещей, чтобы предоставить полный пример исполняемого файла, так как я полагаю, что «код, который вы можете запустить» более полезен, чем что-либо еще.
Допустим, это код, который вы хотите протестировать (сокращен до идентификатора пользователя, чтобы он был короче)
<?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 Some_modelTest.php PHPUnit 3.4.15 Себастьяна Бергманна.
.
Время: 0 секунд, Память: 4,25 МБ
ОК (1 тест, 3 утверждения)
Я очень надеюсь, что это поможет. Это много кода, но в качестве демонстрации он должен работать на вас.