我有一个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
我发现here数组的顺序很重要。我很确定虽然我的所有元素都按照相同的顺序排列,但是如果PHP没有做一些秘密的话。那里提到的解决方案我无法复制,因为我没有$this->assertEquals
而是->with($this->equalTo
语法。
编辑3
我读了here关于在比较之前对数组进行排序的无证参数$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
答案 0 :(得分:0)
我终于得到了它的工作,虽然这是一个妥协。在比较数组之前,我现在正在删除换行符。这不能在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;
}
}