PHPUnit assertEquals 严格类型检查

PHPUnit assertEquals strict type check

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

为此,assertEquals()很遗憾没有用:

$this->assertEquals(
    [ 'prop' => '0' ],
    [ 'prop' => 0 ]
);
// -> no failures

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

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

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

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

我有什么选择?


另外,我不确定为什么要这样设计 - 对我来说,感觉 assertSame() 同时做两件事(我最多有验证过的对象 class, 不是引用).

您可以先检查数组键是否存在,然后检查类型是否正确,例如:

    $this->assertArrayHasKey('prop', $input);
    $this->assertInternalType(\PHPUnit_Framework_Constraint_IsType::TYPE_INT, $input['prop']);
    // or more simply as this->assertTrue(is_int($new_id));
    $this->assertEquals(0, $input['prop']);

希望对您有所帮助

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

/**
 * @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;
}

示例:

$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
// ).

由于您的目标似乎是比较 2 个数组,
需要注意的是,在官方 PHP 手册中 - Array Operators - 描述了对数组 === 运算符的支持

$a === $b Identity TRUE if $a and $b have the same key/value pairs in the same order and of the same types. // same types is only for values - does not check key types

那么你要做的是在一个真实的断言中比较这个结果:

$this->assertTrue(['a' => '1', 'b' => '2'] === ['a' => 1, 'b' => '2']);

assertEquals() 在你的案例中失败了,因为它完全按照它说的做,它用 == 测试 - 我承认的 equal 运算符不是很直观并且带来了一些时髦的东西比如

$this->assertEquals(321, true); // this would PASS!

至于对象,你应该定义一个完整的独立比较器。