提问人:user_51 提问时间:9/19/2023 更新时间:9/20/2023 访问量:35
Symfony ObjectProphecy 以不同的方式对待数组和对象 - 无法更改在 setUp 方法中初始化的数组
Symfony ObjectProphecy treats array and object differently - can't change array which was initialised in setUp method
问:
与此相关
我正在尝试这个测试代码
<?php
use Monolog\Test\TestCase;
use Prophecy\Prophecy\ObjectProphecy;
use Prophecy\Prophet;
class MyBar {
public int $bar = 0;
}
class MyFoo {
public function fooArray(): array {
return [];
}
public function fooBar(): MyBar {
return new MyBar();
}
public function fooInt(): int {
return 0;
}
}
final class SimpleTest extends TestCase
{
private Prophet $prophet;
private ObjectProphecy $mock;
private array $myArray;
private MyBar $myBar;
private int $myInt;
public function getProphet(): Prophet {
return $this->prophet;
}
protected function setUp(): void {
$this->prophet = new Prophet();
$this->myArray = [0];
$this->myBar = new MyBar();
$this->myInt = 0;
$this->mock = $this->getProphet()->prophesize(MyFoo::class);
$this->mock->fooArray()->willReturn($this->myArray);
$this->mock->fooBar()->willReturn($this->myBar);
$this->mock->fooInt()->willReturn($this->myInt);
}
public function test(): void {
$this->myArray = [1];
$this->assertEquals([0], $this->mock->reveal()->fooArray());
$this->myBar->bar = 1;
$this->assertEquals(1, $this->mock->reveal()->fooBar()->bar);
$this->myInt = 1;
$this->assertEquals(0, $this->mock->reveal()->fooInt());
}
}
请注意测试函数的区别,数组不会更新,int 也不会更新,但对象会更新。$myArray
$myInt
$myBar
- 为什么他们不以同样的方式行事?
- 让数组像对象一样工作的推荐方法是什么?
我正在考虑将数组作为引用传递,但据此,使用 .我在顶部链接的问题的答案建议使用另一种方法的解决方案,但我试图看看 中是否有解决方案。ObjectProphecy
MockObject
ObjectProphecy
答:
您正在测试完全不同的东西(将西红柿与马铃薯进行比较)。希望我在下面已经很好地解释了这种情况。
为了回答你的第一个问题,我举了一个例子(但是,这也涉及$this->myInt
$this->myArray
);
在函数中,您使用三个步骤:setup()
第一步是将
0
分配给$this->myInt
:$this->myInt = 0;
第二步是创建一个对象:
$this->mock = $this->getProphet()->prophesize(MyFoo::class);
第三步 是分配值为
0
的对象(来自$this->myInt
):
$this->mock->fooInt()->willReturn($this->myInt);
然后在实际测试函数 ():test()
作为第四步 ,您将
$this->myInt
值更改为1
:$this->myInt = 1;
作为第五步 (#2),您实际上是在测试对象的值,根据
步骤 #3
,该对象
仍应返回0
:$this->assertEquals(0, $this->mock->reveal()->fooInt());
在最后一步中,您实际上是在与您设置的值进行比较(该值符合 )。例如,您的测试将通过。 没有做任何事情,因为你没有改变你的对象(你正在测试的)的值,你只是在改变你的 .只有当测试 的值时,您的预期行为才有效,因此如下所示:0
step #3
$this->myInt = 0
step #1
Step #4
class
$this->myInt
$this->assertEquals(0, $this->myInt);
因此,要解决您的问题,请重写您的测试或确保您正在更改正确的值(在 ur 中或在 .class
object
为了解释您的示例以及为什么会有所不同,您实际上是在更改 your 中的值并在测试中测试相同的值(正确测试):object
object
value
$this->myBar->bar = 1;
$this->assertEquals(1, $this->mock->reveal()->fooBar()->bar);
您更改了 .再一次,您的测试将通过。value
object
要回答第二个问题,请更改为:step #4
$this->myInt = 1;
$this->mock->fooInt()->willReturn($this->myInt);
// and then to do your test from step #5:
$this->assertEquals(0, $this->mock->reveal()->fooInt());
// this should fail.
评论
myBar
object
myArray
array
object
willReturn
int
[int]
myBar
myBar
$this->mock->fooArray()->willReturn($this->myArray);
不会返回动态 .它设置(不是)并将始终返回 。在这里,您正在设置一个对象。它将始终返回对象。在这里,您实际上更新了对象中的值。因此,这将被更新,因为您已经更新了对象中的值。$this->myArray
[0]
$this->myArray
[0]
$this->mock->fooBar()->willReturn($this->myBar);
$this->myBar->bar = 1;
$this->mock->reveal()->fooBar()->bar
int
myBar
string
int
myBar
willReturn
=
int
[int]
willReturn
评论