PHPUnit的:与数组作为参数预期的方法调用(PHPUnit: expect method cal

2019-10-23 13:50发布

我有一个PHPUnit的测试案例,其中我对下面的代码片段不解。 我要检查,该方法actionUpload正确调用函数exposeAndSaveDataLines,即第一个参数是一个数组,因为我希望它是。

public function test_actionUpload()
{
    $sut = $this->getMockBuilder('MasterdataController')
                ->setMethods(array('exposeAndSaveDataLines', 'render'))
                ->disableOriginalConstructor()
                ->getMock();

    $expectedLines = require_once ($this->dataDir . 'expectedLines.php');

    $sut->expects($this->once())
        ->method('exposeAndSaveDataLines')
        ->with($this->equalTo($expectedLines),
            $this->anything(),
            $this->anything(),
            $this->anything(),
            $this->anything());

    $sut->actionUpload();
}

预期的数据是当前阵列的打印输出,具有临时制成print_r (var_export($lines))中的实际代码。 我返回它在文件中expectedLines.php ,当我手动打印,它是正确的。

现在,当我运行测试用例与单个字符在故意拼错expectedLines ,我得到以下错误(如预期)。

Failed asserting that two arrays are equal.
--- Expected
+++ Actual
@@ @@
             3 => 'Colour Group Code'
-            4 => '{2F30E832-D3DB-447E-B733-7BC5125CBCCc}'
+            4 => '{2F30E832-D3DB-447E-B733-7BC5125CBCCC}'
         )
     )
 )

然而,当我纠正错误,但它仍然提到的两个数组不相等。 然而,现在打印整个阵列(至少它的开始,它是一个长阵列),但它没有显示出任何差异(无 - 在任何行的前面+)。 为什么expects法不承认这两个数组是一样的吗? 我怎么能正确测试呢?

编辑1

我已经缩短阵列,使得其打印整个阵列时它们不相等。 仍然没有+或 - 号的比较。

这是我期望的PHP文件的末尾。

    'RetTarget Area' => array(
        0 => array(
            0 => '',
            1 => '',
            2 => '{C19D52BC-834C-45DA-B17F-74D73A2EC0BB}
'
        ),
        1 => array(
            0 => '1',
            1 => '1',
            2 => '{5E25C44F-C18A-4F54-B6B1-248955A82E59}'
        )
    )
);

这是在控制台中我比较输出的结束。

     'RetTarget Area' => Array (
         0 => Array (
             0 => ''
             1 => ''
             2 => '{C19D52BC-834C-45DA-B17F-74D73A2EC0BB}
             '
         )
         1 => Array (...)
     )
 )

我觉得很可疑,最后阵列没有在比较尽显。

编辑2

我发现这里的排列顺序是非常重要的。 我敢肯定,尽管我曾在同一顺序的所有元素,如果PHP没有引擎盖下做一些秘密。 有提到的解决方案,我不能复制的,因为我没有一个$this->assertEquals而是->with($this->equalTo语法。

编辑3

我读到这里大约一个未公开的参数$canonicalize是比较之前下订单的阵列。 当我使用它是这样的:

$sut->expects($this->once())
    ->method('exposeAndSaveDataLines')
    ->with($this->equalTo($expectedLines, $delta = 0.0, $maxDepth = 10, $canonicalize = true, $ignoreCase = false),
        $this->anything(),
        $this->anything(),
        $this->anything(),
        $this->anything());

我看到阵列的秩序确实变了,但我还是看到了同样的错误。 此外,还有一个阵列“坍塌”,我怀疑导致了这个错误。 此外,我不想为了我的所有子阵列,它们应该是在现实和预期的结果相同的顺序。

--- Expected
+++ Actual
@@ @@
 Array (
     0 => Array (
         0 => Array (
             0 => ''
             1 => ''
             2 => '{C19D52BC-834C-45DA-B17F-74D73A2EC0BB}
             '
         )
         1 => Array (...)
     )

编辑4

当我使用identicalTo代替equalTo ,我得到一个更详细的错误信息,说是一个数组不等同于其他的阵列,在打印过程中他们两个。 我复制粘贴他们两个到一个文本文件,并用命令diff命令来检查任何差别,但什么都没有。 尽管如此,PHPUnit的声称,两个阵列是不相等的/相同。

编辑5

当我使用greaterThanOrEqual甚至greaterThan代替equalTo ,则测试通过。 这不会发生的lessThanOrEqual 。 这意味着, 两个阵列之间的差异。

如果我手动更改预期结果弄成一个字符串,它是按字母顺序正确的字符串之前,我lessThan传为好,但那么当然greaterThanOrEqual失败。

编辑6

我越来越相信,在我的数组中的字符串的结束线作这种比较失败,这并不在所有的比较中显示出来。

我现在有以下断言。

public function test_actionUpload_v10MasterdataFile()
{
    ....
    $sut->expects($this->once())
        ->method('exposeAndSaveDataLines')
        ->will($this->returnCallback(function($lines) {
            $expectedLines = include ($this->dataDir . 'ExpectedLines.php');
            $arrays_similar = $this->similar_arrays($lines, $expectedLines);
            PHPUnit_Framework_Assert::assertTrue($arrays_similar);
        }));
    $sut->actionUpload();
}

private function similar_arrays($a, $b)
{
    if(is_array($a) && is_array($b))
    {
        if(count(array_diff(array_keys($a), array_keys($b))) > 0)
        {
            print_r(array_diff(array_keys($a), array_keys($b)));
            return false;
        }

        foreach($a as $k => $v)
        {
            if(!$this->similar_arrays($v, $b[$k]))
            {
                return false;
            }
        }

        return true;
    }
    else
    {
        if ($a !== $b)
        {
            print_r(PHP_EOL . 'A: '. $a. PHP_EOL . 'Type: ' . gettype($a) . PHP_EOL);
            print_r(PHP_EOL . 'B: '. $b. PHP_EOL . 'Type: ' . gettype($b) . PHP_EOL);
        }
        return $a === $b;
    }
}

结果如下。

A: {72C2F175-9F50-4C9C-AF82-9E3FB875EA82}

Type: string

B: {72C2F175-9F50-4C9C-AF82-9E3FB875EA82}

Type: string

Answer 1:

我终于得到它的工作,虽然这是一个有点妥协。 之前我比较阵列我现在除去换行符。 这不能在完成with方法,所以我提出了以下建设。

public function test_actionUpload_v10MasterdataFile()
{
    /*
     * Create a stub to disable the original constructor.
     * Exposing data and rendering are stubbed.
     * All other methods behave exactly the same as in the real Controller.
     */
    $sut = $this->getMockBuilder('MasterdataController')
                ->setMethods(array('exposeAndSaveDataLines', 'render'))
                ->disableOriginalConstructor()
                ->getMock();

    $sut->expects($this->once())
        ->method('exposeAndSaveDataLines')
        ->will($this->returnCallback(function($lines) {
            $expectedLines = include ($this->dataDir . 'ExpectedLines.php');
            PHPUnit_Framework_Assert::assertTrue($this->similar_arrays($lines, $expectedLines));
        }));

    // Execute the test
    $sut->actionUpload();
}

...

private function similar_arrays($a, $b)
{
    /**
     * Check if two arrays have equal keys and values associated with it, without
     * looking at order of elements, and discarding newlines.
     */
    if(is_array($a) && is_array($b))
    {
        if(count(array_diff(array_keys($a), array_keys($b))) > 0)
        {
            return false;
        }

        foreach($a as $k => $v)
        {
            if(!$this->similar_arrays($v, $b[$k]))
            {
                return false;
            }
        }
        return true;
    }
    else
    {
        $a = rtrim($a);
        $b = rtrim($b);
        $extended_output = false;
        if ($extended_output && ($a !== $b))
        {
            print_r(PHP_EOL . 'A: '. $a. PHP_EOL . 'Type: ' . gettype($a) . PHP_EOL);
            print_r(PHP_EOL . 'B: '. $b. PHP_EOL . 'Type: ' . gettype($b) . PHP_EOL);
        }
        return $a === $b;
    }
}


文章来源: PHPUnit: expect method call with array as argument