Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/242.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
PHPUnit测试中意外更改的变量_Php_Laravel_Phpunit - Fatal编程技术网

PHPUnit测试中意外更改的变量

PHPUnit测试中意外更改的变量,php,laravel,phpunit,Php,Laravel,Phpunit,我编写了一个简单的单元测试,测试被测试类上的方法是否返回自身的实例,并且传递的参数保持不变 即$this->class->method$param1,$param2;不应修改$param1或$param2,因为该方法返回$this。但是,我看到,当我在运行该方法后立即var_转储$param1时,$param1已经被修改 要提供更多上下文: 假设有一个名为Bob Jones的用户 Bob有一些元用户数据,这些数据还具有相同值的属性name和姓氏 当我将UserData元数据对象中的name属性更

我编写了一个简单的单元测试,测试被测试类上的方法是否返回自身的实例,并且传递的参数保持不变

即$this->class->method$param1,$param2;不应修改$param1或$param2,因为该方法返回$this。但是,我看到,当我在运行该方法后立即var_转储$param1时,$param1已经被修改

要提供更多上下文:

假设有一个名为Bob Jones的用户

Bob有一些元用户数据,这些数据还具有相同值的属性name和姓氏

当我将UserData元数据对象中的name属性更改为“Fred”时

我在对象之间同步数据,即调用被测方法

注意:此时-如果我``var\u dump$user->name;```*Fred*'是输出,而不是我所期望的“*Bob*”。 然后用户对象仍应具有名称“Bob”

如上所述,$user对象已经更改,没有任何直接修改

为完整起见,完整代码如下:

SyncUserDataTest.php

SyncUserData.php


很简单,我的问题是,$user对象的name属性是如何更改的?

您似乎遇到的问题是,默认情况下对象是通过引用传递的,因此当您更新一个对象时,您会更新所有对象

解决方法包括但不限于:

使用克隆虽然这只做浅拷贝,但要注意这一点 序列化然后将对象反序列化为新变量
没有看太多的代码;博士,我的意思是你被引用传递的对象弄糊涂了。如果您更改共享同一引用的变量的值,它们都会显示为已更新,尽管实际上,它们都是相同的。没有任何东西是通过引用传递的,即使是,我传递对象的同步方法也不会直接修改$user对象。默认情况下,对象是通过引用传递的。啊,这是有意义的。您并不经常真正需要对象的克隆,因此在本例中,由于这是预期的功能,因此必须显式定义它。请随时写下你最后的评论作为回答,这样我可以标记它给你的信用。
$user = factory(App\User::class, 'withCompany')
        ->make([
            'name' => 'Bob',
            'surname' => 'Jones',
            'member_id' => 1
        ]);
$userData = factory(App\UserData::class)
        ->make($this->mapUserToUserData($user) + ['member_id' => 1]);
$userData->m_field_id_4 = 'Fred';
$this->syncUserData->sync($user, $userData);
$originalUser = $this->syncUserData->getOriginalUser();
$syncedUser = $this->syncUserData->getSyncedUser();

$this->assertEquals('Bob', $originalUser->name);
$this->assertEquals('Fred', $syncedUser->name);
class SyncUserDataTest extends TestCase
{
use UserDataMapper;

protected $syncUserData;

public function setUp()
{
    parent::setUp();

    $this->syncUserData = new App\Helpers\SyncUserData();
}
public function test_it_returns_the_unmodified_user()
{
    $user = factory(App\User::class, 'withCompany')
        ->make([
            'name' => 'Bob',
            'member_id' => 1
        ]);
    $userData = factory(App\UserData::class)
        // And the data is the same
        ->make($this->mapUserToUserData($user) + ['member_id' => 1]);

    $userData->m_field_id_4 = 'Fred';

    $this->syncUserData->sync($user, $userData);

    $originalUser = $this->syncUserData->getOriginalUser();
    $syncedUser = $this->syncUserData->getSyncedUser();

    $this->assertEquals('Bob', $originalUser->name);
    $this->assertEquals('Fred', $syncedUser->name);
}

}
<?php

namespace App\Helpers;

class SyncUserData
{
/**
 * Has any data changed.
 *
 * @var bool
 */
private $hasChanged = false;

/**
 * The original User object without modifications.
 *
 * @var \App\User
 */
private $originalUser;

/**
 * The updated User object that has had data synced from the UserData object.
 *
 * @var \App\User
 */
private $syncedUser;

/**
 * Sync data from UserData with a User object.
 *
 * @param   \App\User $user
 * @param   \App\UserData $against
 * @return  $this
 */
public function sync($user, $against)
{
    $this->setOriginalUser($user);

    $updatedUser = $this->applyChangesToUser($user, $against);

    $this->setSyncedUser($updatedUser);

    return $this;
}

/**
 * Check if two values are the same.
 *
 * @param string $check
 * @param string $against
 * @return bool
 */
public function hasChanged($check, $against)
{
    if ($check != $against) {
        $this->hasChanged = true;

        return true;
    }

    return false;
}

/**
 * @param \App\User $user
 * @return $this
 */
public function setSyncedUser($user)
{
    $this->syncedUser = $user;
    return $this;
}

/**
 * @param \App\User $user
 * @return $this
 */
public function setOriginalUser($user)
{
    $this->originalUser = $user;
    return $this;
}


/**
 * Get the updated User object with data synced from the UserData object.
 *
 * @access public
 * @return mixed
 */
public function getSyncedUser()
{
    return $this->syncedUser;
}

/**
 * Get the original User object.
 *
 * @access public
 * @return mixed
 */
public function getOriginalUser()
{
    return $this->originalUser;
}

/**
 * Was any data different between the User and UserData objects.
 *
 * @access public
 * @return bool
 */
public function wasDataChanged()
{
    return $this->hasChanged;
}

/**
 * @param $user
 * @param $against
 */
private function applyChangesToUser($user, $against)
{
    if ($this->hasChanged($user->name, $against->m_field_id_4)) {
        $user->name = $against->m_field_id_4;
    }

    if ($this->hasChanged($user->surname, $against->m_field_id_5)) {
        $user->surname = $against->m_field_id_5;
    }

    return $user;
}

}