A PHPUnit data provider allows the return of an iterator,但在使用AppendIterator时,仅使用附加的最后一个迭代器。我设置错了还是AppendIterators不能用作PHPUnit数据提供者?
测试文件:
<?php
use PHPUnit\Framework\TestCase;
class AppendIteratorTest extends TestCase
{
/**
* @dataProvider getAppendIterator
*/
public function testAppendIterator($item) {
echo PHP_EOL."test> $item".PHP_EOL;
}
public function getAppendIterator() {
$iterator = new AppendIterator();
$iterator->append(new ArrayIterator([[0], [1]]));
$iterator->append(new ArrayIterator([[2], [3]]));
$iterator->append(new ArrayIterator([[4], [5]]));
foreach($iterator as $i) {
echo 'foreach> '.print_r($i, true);
}
return $iterator;
}
}
测试文件输出:
$ vendor/bin/phpunit --debug AppendIteratorTest.php
foreach> Array
(
[0] => 0
)
foreach> Array
(
[0] => 1
)
foreach> Array
(
[0] => 2
)
foreach> Array
(
[0] => 3
)
foreach> Array
(
[0] => 4
)
foreach> Array
(
[0] => 5
)
PHPUnit 6.2.3 by Sebastian Bergmann and contributors.
Starting test 'AppendIteratorTest::testAppendIterator with data set #0 (4)'.
R
test> 4
Starting test 'AppendIteratorTest::testAppendIterator with data set #1 (5)'.
R 2 / 2 (100%)
test> 5
Time: 24 ms, Memory: 4.00MB
There were 2 risky tests:
1) AppendIteratorTest::testAppendIterator with data set #0 (4)
This test did not perform any assertions
2) AppendIteratorTest::testAppendIterator with data set #1 (5)
This test did not perform any assertions
OK, but incomplete, skipped, or risky tests!
Tests: 2, Assertions: 0, Risky: 2.
答案 0 :(得分:0)
我设置错误还是AppendIterators不能用作PHPUnit数据提供者?
有点错误。 Phpunit中的数据提供者支持任何 Traversable
或 AppendIterator
( Traversable
是 Traversable
的)。所以它确实有效(你可以看到这一点,因为你没有得到错误)。
然而,数据提供者有一个(鲜为人知的)细节:每个数据集都可以有一个名称。如果 Iterator::key()
的值为ArrayIterator
,则名称是提供的数组的键 - 或 - 。对于作为数组键的 $iterator->append(new ArrayIterator([0 => [0], 1 => [1]]));
$iterator->append(new ArrayIterator([0 => [2], 1 => [3]]));
$iterator->append(new ArrayIterator([0 => [4], 1 => [5]]));
。
这里你的密码代码可见,因为PHP会隐式创建它们:
$iterator->append(new ArrayIterator([0 => [0], 1 => [1]]));
$iterator->append(new ArrayIterator([2 => [2], 3 => [3]]));
$iterator->append(new ArrayIterator([4 => [4], 5 => [5]]));
在你的键中,这些键总是0和1.因为你有重复的键,最后的键将“赢”。这是你看到的结果。
解释发生了什么。
然后可以是一个解决方案:
IndexingIterator
PHP中没有默认的Iterator可以重新为密钥编号,我在Iterator Garden( public function getAppendIterator() {
$iterator = new AppendIterator();
$iterator->append(new ArrayIterator([[0], [1]]));
$iterator->append(new ArrayIterator([[2], [3]]));
$iterator->append(new ArrayIterator([[4], [5]]));
$index = 0;
foreach ($iterator as $i) {
yield $index++ => $i;
}
}
中没有密码,Börgers示例是向下,Nikic iter lib's reindex
可以做到,...)你的案例中的快速内联将会产生重新索引:
$index
此处yield
计数器用作Generator
语句中的键。这会使您的数据提供者再次返回 Traversable
,这是 activeadmin
。然后Phpunit可以处理它。
当您有多个数据提供程序方法使用字符串键返回数据集时,问题类似。所有字符串键必须是唯一的,否则提供的数据将被重写。
这是内部的b / c,来自每个数据提供者的数据集明确地变成了一个数组。
我希望这可以回答您的问题并帮助您创建您正在寻找的数据提供者。
答案 1 :(得分:0)
使用foreach语法是有区别的。
(a)foreach ($iterator as $key => $value) { echo "$key = $value\n"; }
(b)foreach ($iterator as $value) { echo "$value\n"; }
在循环中使用键时,由于键值重复,将出现问题。因此,最后一个值获胜。在情况(b)中,当不使用密钥时,迭代将根据附加迭代器的顺序进行。请注意,在情况(b)中显示了所有值。
有一种方法可以从称为iterator_to_array
的迭代器中提取所有值。此方法可以帮助您解决键重复的问题。它有一个附加参数,即不使用原始密钥。它将为每个值创建一个新的唯一数字索引。
示例$all_values = iterator_to_array($iterator, false);
我知道这是一个古老的话题,但是答案可能对其他用户有帮助。