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