phpunit:为什么这个 assertContains 通过了?

phpunit: why does this assertContains pass?

我的测试应该失败,但它通过了:

public function test_getValidProviderCodes(){
    $aTest = PRIDE\Reflection::executeStaticMethodForClassName(Apps_DoctorsReports::class, "getValidProviderCodes");
    print_r($aTest);
    $this->assertContains("xxxxxxxxxxxxxx", $aTest);
}

输出:

Testing started at 8:53 AM ...
PHPUnit 4.6.6 by Sebastian Bergmann and contributors.

Configuration read from C:\inetpub\Intranet_Local\phpunit\phpunit.xml

Array
(
    [0] => 0
    [1] => 1
    [2] => 2
    [3] => MAYER
    [4] => MAY00
    [5] => MAYERIC
    [6] => COH00
    [7] => COH01
    [8] => POWELL
    [9] => POW00
    [10] => JOHN00
    [11] => FINO
    [12] => POL01
    [13] => NONAP
    [14] => RAYE00
    [15] => HOPS00
    [16] => CHAH00
)
 - 


Time: 1.24 seconds, Memory: 8.25Mb

OK (1 test, 1 assertion)

"xxxxxxxxxxxxxx"显然不在那个数组中。我已经使用此功能数百次,但从未见过这种行为。

(如果我将 $aTest 更改为 [],测试会失败。)


这是另一个测试运行:

public function test_getValidProviderCodes(){
    $aTest = PRIDE\Reflection::executeStaticMethodForClassName(Apps_DoctorsReports::class, "getValidProviderCodes");
    $this->assertContains("S01", implode(", ", $aTest));
}

输出:

Testing started at 9:04 AM ...
PHPUnit 4.6.6 by Sebastian Bergmann and contributors.

Configuration read from C:\inetpub\Intranet_Local\phpunit\phpunit.xml


Failed asserting that '0, 1, 2, M01, M03, M04, M05, N02, C01, C02, C03, C04, P01, P02, P03, P04, P05, P06, P07, R01, H01, J01, J02' contains "S01".
 C:\inetpub\Intranet_Local\phpunit\library\classes\apps\DoctorsReportsTest.php:61



Time: 1.54 seconds, Memory: 8.75Mb


FAILURES!
Tests: 1, Assertions: 1, Failures: 1.

assertContains 也可以检查对象标识(默认行为)。因此,要跳过这个,您需要将一个可选标志传递给该方法。这个问题已经解决了here on github

所以要使您的测试失败,只需传递最后一个可选参数 checkForNonObjectIdentitytrue,如下所示:

public function test_getValidProviderCodes(){

    $aTest =
        array(
            0,1,2,'MAYER'
        );
    print_r($aTest);
    $this->assertContains(
        "xxxxxxxxxxxxxx",
        $aTest,
        'message',
        false,true,true);

}

输出:

Failed asserting that an array contains 'xxxxxxxxxxxxxx'.

希望对您有所帮助

截至 2017 年 1 月,PHPUnit appears to have a regression bug 导致此行为,并且设置 checkForNonObjectIdentity 标志不是解决方案。

但是,您可以通过这种方式通过严格的类型检查实现 assertContains 类型的行为:

$this->assertTrue( in_array( $arguments, $calls, TRUE ) );

The third argument to in_array is the strict flag,设置为TRUE.

时强制进行类型检查

我在辅助函数中使用了这种技术,该函数检查模拟方法调用列表中是否存在参数列表。在我发现 FALSE[] 被视为相等后,我不得不更改此函数以进行严格类型化,因此导致测试通过,但本应失败。

protected function assertCalledWith( $mock, $method, $arguments ) {
    $calls = $mock->getCalls( $method );
    $mockName = get_class( $mock );
    $error = "Failed asserting that $mockName->$method() was called with specified args.";
    $this->assertTrue( in_array( $arguments, $calls, TRUE ), $error );
}