在PHPUnit测试

时间:2015-09-04 08:22:29

标签: php laravel phpunit

我编写了一个简单的单元测试,它测试一个被测试类的方法返回一个自身的实例,传递的参数不受影响。

即。由于方法返回$this->theClass->theMethod($param1, $param2);$param1不应修改$param2$this。但是,我在运行该方法后立即var_dump($param1)看到$ param1已被修改。

提供更多背景信息:

鉴于有User名为 Bob Jones

$user = factory(App\User::class, 'withCompany')
        ->make([
            'name' => 'Bob',
            'surname' => 'Jones',
            'member_id' => 1
        ]);

并且 Bob 有一些元UserData,其中还有属性namesurname(值相等)。

$userData = factory(App\UserData::class)
        ->make($this->mapUserToUserData($user) + ['member_id' => 1]);

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

$userData->m_field_id_4 = 'Fred';

我同步对象之间的数据(即我称之为测试方法)

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

注意:此时 - 如果我```var_dump($ user-> name);```,' * Fred *'正如我所期望的那样输出,而不是' * Bob *&#39 ;.

然后,User对象仍应保留名称' Bob '

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

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

如上面的注释所述,$user对象已被更改,没有任何直接修改。

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

SyncUserDataTest.php

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);
}

}

SyncUserData.php

<?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;
}

}

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

1 个答案:

答案 0 :(得分:0)

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

这方面的方法包括(但可能不限于):

  • 使用克隆(虽然这只是一个浅拷贝,所以请注意)
  • 序列化然后将对象反序列化为新变量