7

我从 API 获取 JSON 结构,需要检查成功响应是否具有两个具有特定值的特定属性。

关键问题:

  1. 我无法比较整个对象,因为有一些属性可能因每个请求而异
  2. 我不能编写两个测试(针对每个属性),因为只有当两个属性都匹配正确的值时,它才能被视为成功响应。

成功响应示例:

{
    'success': true,
    'user_ip': '212.20.30.40',
    'id': '7629428643'
}

肮脏的解决方案是

<?php
public function testAddAccount() {
    $response = $this->api->addAccount( '7629428643' );

    $this->assertTrue(
        $response->success === TRUE &&
        $response->id === '7629428643'
    );
}

但我认为必须有更好更清洁的解决方案,是吗?

4

6 回答 6

2

您要assertEquals()用于要验证的每个属性。虽然您通常只想在每个测试用例中测试一件事,但有时需要多个断言才能测试“一件事”。因此,多个断言是可以的。

您可能还想断言属性存在于$response对象上以避免通知。有关示例,请参见以下内容:

public function testAddAccount() {
    // Attempt to create an account.
    $response = $this->api->addAccount('7629428643');

    // Verify that the expected properties are present in the response.
    $this->assertObjectHasAttribute('success', $response);
    $this->assertObjectHasAttribute('id', $response);

    // Verify the values of the properties.
    $this->assertEquals(true, $response->success);
    $this->assertEquals('7629428643', $response->id);
}
于 2012-08-21T15:40:35.050 回答
1

计算响应和正确答案之间的差异,忽略任何过高的值。如果没有区别,一切都很好;如果有,您将获得完整的信息。

//some examples
$responseValues = array('success' => true, 'user_ip' => '212.20.30.40', 'id' => '7629428643'); //success
$errorResponseValues = array('success' => false, 'user_ip' => '212.20.30.40', 'id' => '7629428643'); //failure
$errorResponseValues2 = array('success' => false, 'user_ip' => '212.20.30.40', 'id' => '123'); //failure

$expectedValues = array('success' => true, 'id' => '7629428643'); //what is success

function whatIsWrong($reality, $expectation)
{
    return array_uintersect_assoc($reality, $expectation, function($a, $b){return (int)($a == $b);}); //This is slightly dirty, I think the final implementation is up to you
}

var_dump(whatIsWrong($responseValues, $expectedValues)); //array()
var_dump(whatIsWrong($errorResponseValues, $expectedValues)); //array('success' => false)
var_dump(whatIsWrong($errorResponseValues2, $expectedValues)); //array('success' => false, id => 123)

然后你可以使用 assertEqual(whatIsWrong(...), array()),它应该在失败时输出差异,或者以几乎任何首选的方式处理它。

于 2012-08-26T22:44:51.777 回答
0

如某些答案所述,您应该使用assertEquals()方法。第二部分是您可能会使用一些断言。因此,如果 phpunit 在第一个断言上检测到失败,则整个测试都会失败。

为什么不使用assertTrue()?因为不清楚您是否,例如,if ($object) ...在代码的一个地方和另一个地方使用assertTrue($object);

此外,请确保您的例程正确执行。因此,如果您在尝试获取响应时遇到异常 - 测试将失败。虽然异常也应作为测试用例进行检查。也就是说,您应该尝试发布不正确的请求并抛出断言异常。这就是好的测试的样子——它应该检查所有可能的情况,呵呵=)

所以,这是你应该得到的代码:

public function testAddAccount() {
    $response = $this->api->addAccount('7629428643');

    $this->assertEquals($response->success, true);
    $this->assertEquals($response->id, '7629428643');

    $this->setExpectedException('MyException');

    $response = $this->api->addAccount('wrong_account');
}
于 2012-08-17T17:13:04.550 回答
0

如果assertTrue()存储成功响应的布尔值,这就是我处理它的方式。请记住,这是一个口味问题。

private $lastResponse;
// $id given elsewhere
public function testAddAccount($id) {
   $this->lastResponse = $this->addAccount($id);
}

private function addAccount($id) {
   return $this->api->addAccount($id);
}

private function isLastResponseValid($response){
   return $this->lastResponse->success === TRUE 
   && $this->lastResponse->id === '7629428643';
}
于 2012-08-03T14:04:10.160 回答
0

我能想到的最简洁的方法(尽管这一个口味问题)是添加两个布尔表达式并断言结果是两个:

$r1=$response->success === TRUE;
$r2=$response->id === '7629428643';
$this->assertEquals(2, $r1+$r2, "Expecting both values to match; got ($r1) and ($r2)");

当然,您可以将此设置扩展到任意数量的带有数组和的测试array_sum()==count(),以及更可爱的消息。

于 2012-08-26T22:07:06.097 回答
0

对于这种情况,您可以在单个测试方法中使用多个断言。此外,尽可能使用更具体的断言,assertEquals因为这些断言会提供更好的失败消息。

public function testAddAccount() {
    $response = $this->api->addAccount( '7629428643' );

    self::assertTrue($response->success);
    self::assertEquals('7629428643', $response->id);
}
于 2012-08-06T09:33:59.590 回答