kei*_*ant 9 php collections phpunit unit-testing stub
我正在为课程构建单元测试Foo,而且我对单元测试也很新.
我的类的一个关键组件是一个BarCollection包含许多Bar对象的实例.Foo迭代集合的一种方法是在集合中的每个Bar对象上调用几个方法.我想使用存根对象为我的测试类生成一系列响应.在Bar迭代时如何使存根类返回不同的值?我试图沿着这些方向做点什么:
$stubs = array();
foreach ($array as $value) {
$barStub = $this->getMock('Bar');
$barStub->expects($this->any())
->method('GetValue')
->will($this->returnValue($value));
$stubs[] = $barStub;
}
// populate stubs into `Foo`
// assert results from `Foo->someMethod()`
Run Code Online (Sandbox Code Playgroud)
因此,Foo->someMethod()将根据从Bar对象接收的结果生成数据.但是,只要数组长于1,就会出现以下错误:
There was 1 failure:
1) testMyTest(FooTest) with data set #2 (array(0.5, 0.5))
Expectation failed for method name is equal to <string:GetValue> when invoked zero or more times.
Mocked method does not exist.
/usr/share/php/PHPUnit/Framework/MockObject/Mock.php(193) : eval()'d code:25
Run Code Online (Sandbox Code Playgroud)
我有一个想法是用来->will($this->returnCallback())调用一个回调方法,但我不知道如何向回调指示哪个Bar对象正在进行调用(以及因此给出的响应).
另一个想法是使用onConsecutiveCalls()方法或类似的东西告诉我的存根第一次返回1,第二次返回2等,但我不确定如何做到这一点.我还担心如果我的班级除了对集合进行有序迭代之外还做了什么,我将无法测试它.
不幸的是,我不确定您是否可以使用getMock()解决您的实际问题,但我对getMock()本身的经验很少。
我唯一能想到的事情,但不知道你的Bar类,这可能没有帮助: getMock()的第三个参数允许你传递构造函数参数(作为数组)。
我将创建我自己的模拟类,扩展 Bar 作为测试助手(“只是另一个类,恰好仅在测试中使用”的奇特名称),它完全按照我喜欢的方式进行操作,并将一系列它们注入到您的Foo对象中。这为您提供了所需的所有控制,因为您可以直接替换有问题的方法,而getMock()则不这样做。当然,这也意味着您不会在此测试中测试Bar类,这可能不是您想要的 - 尽管我建议无论如何为每个测试类编写一个单独的测试类,但在某些情况下,这是不必要的纯粹主义。
$stubs = array();
foreach ($array as $value) {
$stubs[] = new MyBarTestHelper($value);
}
Run Code Online (Sandbox Code Playgroud)
除此之外,我真的很惊讶你只看到当你有多个数组元素时描述的异常。我观察到,PHPUnit 实际上希望您声明任何您希望它能够作为getMock()参数进行跟踪的方法,否则将会错误地输出,因为本质上它在内部所做的是创建自己的类扩展,用逻辑包装您明确声明的每个方法,使其确定是否调用该方法(= 将方法名称添加到逻辑列表中)。
所以,我很天真(说真的,我可能是,我自己是一个测试新手),但看看这是否对你有帮助:
$stubs = array();
foreach ($array as $value) {
$barStub = $this->getMock('Bar', array('GetValue'));
$barStub->expects($this->any())
->method('GetValue')
->will($this->returnValue($value));
$stubs[] = $barStub;
}
Run Code Online (Sandbox Code Playgroud)