PHPUnit assertEquals 严格的类型检查

Chr*_*ian 5 phpunit assertions

我的目标是确保对象图具有预期的值和类型。我想确保每个值都是预期的类型。

为此,assertEquals()不幸的是没有用:

$this->assertEquals(
    [ 'prop' => '0' ],
    [ 'prop' => 0 ]
);
// -> no failures
Run Code Online (Sandbox Code Playgroud)

在这种情况下,assertSame()效果很好:

$this->assertSame(
    [ 'prop' => '0' ],
    [ 'prop' => 0 ]
);
// Failed asserting that Array &0 (
//     'prop' => 0
// ) is identical to Array &0 (
//     'prop' => '0'
// ).
Run Code Online (Sandbox Code Playgroud)

问题assertSame()在于它还检查对象的引用:

$this->assertSame(
    (object) [ 'prop' => 0 ],
    (object) [ 'prop' => 0 ]
);
// Failed asserting that two variables reference the same object.
Run Code Online (Sandbox Code Playgroud)

我有哪些选择?


另外,我不确定为什么要以这种方式设计 - 对我来说,感觉同时assertSame()做两件事(我最多有经过验证的对象类,而不是引用)。

Chr*_*ian 2

到目前为止,我提出了以下选项:

/**
 * @param mixed $expected
 * @param mixed $actual
 * @param string $message
 */
public function assertObjectGraph($expected, $actual, $message = '')
{
    $expected = $this->convertObjectsToHashes($expected);
    $actual = $this->convertObjectsToHashes($actual);

    $this->assertSame($expected, $actual, $message);
}

/**
 * @param mixed $value
 * @return mixed
 */
private function convertObjectsToHashes($value)
{
    if (is_object($value)) {
        $value = ['__CLASS__' => get_class($value)] + get_object_vars($value);
    }

    if (is_array($value)) {
        $value = array_map([$this, __FUNCTION__], $value);
    }

    return $value;
}
Run Code Online (Sandbox Code Playgroud)

例子:

$this->assertObjectGraph(
    (object) [ 'prop' => 0 ],
    (object) [ 'prop' => 0 ]
);
// -> ok

$this->assertObjectGraph(
    (object) [ 'prop' => 0 ],
    (object) [ 'prop' => '0' ],
);
// Failed asserting that Array &0 (
//     '__CLASS__' => 'stdClass'
//     'prop' => '0'
// ) is identical to Array &0 (
//     '__CLASS__' => 'stdClass'
//     'prop' => 0
// ).

class Test{public $prop = 0;}
$this->assertObjectGraph(
    (object) [ 'prop' => 0 ],
    new Test()
);
// Failed asserting that Array &0 (
//     '__CLASS__' => 'Test'
//     'prop' => 0
// ) is identical to Array &0 (
//     '__CLASS__' => 'stdClass'
//     'prop' => 0
// ).
Run Code Online (Sandbox Code Playgroud)