Mockery/PhpUnit: 测试成功但错误
Mockery/PhpUnit: test is successful but it is wrong
我有一个 Domoticz class,读取外部 API。
class Domoticz extends HeaterService implements DomoticControllerInterface {
public function getFromApiCurrentHeaterStatus($current_heater)
{
$current_heater = json_decode($current_heater);
if (!isset($current_heater->result)) {
throw new \Exception('There is a problem retrieving heater status');
}
$heater = array();
foreach ($current_heater->result as $result) {
$heater['idx'] = (int)$result->idx;
$heater['status'] = $result->Status;
}
return $heater;
}
}
方法getFromApiCurrentHeaterStatus
returns一个数组。
这是我的测试
class DomoticzTest extends TestCase
{
/**
* This is a copy of real json got from an API call
*/
private $heater_answer = '{"result":{"2":{"Status":"Off","idx":"17"}}}';
/**
* Test that from an answer as $heater_answer, we can get an array with idx and status
*
*/
public function testThatWeCanGetAnArrayFromHeaterAnswer()
{
$right_heater_array = array('idx' => 17, 'status' => 'Off');
$right_array_we_want = $right_heater_array; // we need to get an array
$wrong_heater_array = array('idx' => 11, 'status' => 'On');
$wrong_array_we_dont_want = $wrong_heater_array;
$mock = $this->getMockBuilder('\App\Libs\Domoticz')
->disableOriginalConstructor()
->getMock();
$mock
->expects($this->once())
->method('getFromApiCurrentHeaterStatus')
->with($this->heater_answer)
->willReturn($right_array_we_want);
$heater = $mock->getFromApiCurrentHeaterStatus($this->heater_answer);
$this->assertEquals($right_array_we_want,$heater);
}
测试通过。实际上,通过 "real" API 调用 ($this->heater_answer
),我们得到一个数组
$heater['idx'] = 17;
$heater['status'] = 'Off';
现在,我确实尝试更改 属性 heater_answer
,将 idx 从 17 更改为 2,例如,或状态,在每种情况下测试都通过。
换句话说:真正的方法是没有执行?如何强制测试真正执行真正的方法?
你为什么要嘲笑它?您没有在该方法中进行实际的 API 调用..
由于您正在测试您的方法是否将实际的 heater 答案解码为正确的格式,因此您的测试应如下所示:
private $heater_answer = '{"result":{"2":{"Status":"Off","idx":"17"}}}';
public function testThatWeCanGetAnArrayFromHeaterAnswer()
{
$mock = $this->getMockBuilder('\App\Libs\Domoticz')
->setMethodsExcept(['getFromApiCurrentHeaterStatus'])
->disableOriginalConstructor()
->getMock();
$response = $mock->getFromApiCurrentHeaterStatus($this->heater_answer);
$this->assertEquals([
'idx' => 17,
'status' => 'Off'
], $response);
}
通过添加 setMethodsExcept()
,该数组中定义的方法将不会被测试替身替换。然后你可以实际测试它。
我有一个 Domoticz class,读取外部 API。
class Domoticz extends HeaterService implements DomoticControllerInterface {
public function getFromApiCurrentHeaterStatus($current_heater)
{
$current_heater = json_decode($current_heater);
if (!isset($current_heater->result)) {
throw new \Exception('There is a problem retrieving heater status');
}
$heater = array();
foreach ($current_heater->result as $result) {
$heater['idx'] = (int)$result->idx;
$heater['status'] = $result->Status;
}
return $heater;
}
}
方法getFromApiCurrentHeaterStatus
returns一个数组。
这是我的测试
class DomoticzTest extends TestCase
{
/**
* This is a copy of real json got from an API call
*/
private $heater_answer = '{"result":{"2":{"Status":"Off","idx":"17"}}}';
/**
* Test that from an answer as $heater_answer, we can get an array with idx and status
*
*/
public function testThatWeCanGetAnArrayFromHeaterAnswer()
{
$right_heater_array = array('idx' => 17, 'status' => 'Off');
$right_array_we_want = $right_heater_array; // we need to get an array
$wrong_heater_array = array('idx' => 11, 'status' => 'On');
$wrong_array_we_dont_want = $wrong_heater_array;
$mock = $this->getMockBuilder('\App\Libs\Domoticz')
->disableOriginalConstructor()
->getMock();
$mock
->expects($this->once())
->method('getFromApiCurrentHeaterStatus')
->with($this->heater_answer)
->willReturn($right_array_we_want);
$heater = $mock->getFromApiCurrentHeaterStatus($this->heater_answer);
$this->assertEquals($right_array_we_want,$heater);
}
测试通过。实际上,通过 "real" API 调用 ($this->heater_answer
),我们得到一个数组
$heater['idx'] = 17;
$heater['status'] = 'Off';
现在,我确实尝试更改 属性 heater_answer
,将 idx 从 17 更改为 2,例如,或状态,在每种情况下测试都通过。
换句话说:真正的方法是没有执行?如何强制测试真正执行真正的方法?
你为什么要嘲笑它?您没有在该方法中进行实际的 API 调用..
由于您正在测试您的方法是否将实际的 heater 答案解码为正确的格式,因此您的测试应如下所示:
private $heater_answer = '{"result":{"2":{"Status":"Off","idx":"17"}}}';
public function testThatWeCanGetAnArrayFromHeaterAnswer()
{
$mock = $this->getMockBuilder('\App\Libs\Domoticz')
->setMethodsExcept(['getFromApiCurrentHeaterStatus'])
->disableOriginalConstructor()
->getMock();
$response = $mock->getFromApiCurrentHeaterStatus($this->heater_answer);
$this->assertEquals([
'idx' => 17,
'status' => 'Off'
], $response);
}
通过添加 setMethodsExcept()
,该数组中定义的方法将不会被测试替身替换。然后你可以实际测试它。