在 PhpUnit 测试中匹配 Json 结构 - Laravel 5.4

39

我正在创建一个单元测试,想要测试响应中返回的 JSON 结构。我知道 TestResponse 提供了一个 assertJsonStructure 方法来匹配你的 JSON 响应的结构。但由于某些原因,我无法将 $structure 映射到我的响应中,结果测试失败。让我分享所需的代码片段。

端点响应

{
   "status": true,
   "message": "",
   "data": [
       {
          "id": 2,
          "name": "Shanelle Goodwin",
          "email": "chaz43@example.net",
          "created_at": "2017-03-05 16:12:49",
          "updated_at": "2017-03-05 16:12:49",
          "user_id": 1
       }
    ]
}

测试函数

public function testEndpoint(){

  $response = $this->get('/api/manufacturer/read', [], $this->headers);
  $response->assertStatus(200);
  $response->assertJsonStructure([
    'status',
    'message',
    'data' => [
      {
        'id',
        'name',
        'email',
        'created_at',
        'updated_at',
        'user_id'
      }
    ]
  ]);
  var_dump("'/api/manufacturer/read' => Test Endpoint");
}

data数组中可能有多个节点,所以我尝试在结构中提到该数组,但似乎映射不正确。任何帮助将不胜感激:-)

2个回答

107

幸运的是,通过尝试不同的选项,我解决了这个问题。如果我们要匹配数组中嵌套对象的话,需要使用 '*' 作为键值。我们可以在这里看到相应的参考。

来源:TestResponse

我已经将结构设置为这样的 `array of objects`

$response->assertJsonStructure([
    'status',
    'message',
    'data' => [
      '*' => [
        'id',
        'name',
        'email',
        'created_at',
        'updated_at',
        'user_id'
      ]
    ]
  ]);

如果您只想匹配单个对象

$response->assertJsonStructure([
    'status',
    'message',
    'data' => [
      [
        'id',
        'name',
        'email',
        'created_at',
        'updated_at',
        'user_id'
      ]
    ]
  ]);

7
非常有用!应该出现在官方文档中。感谢你为我们找到了这个信息。 - Jannie Theunissen
1
代码已经移动:https://github.com/laravel/framework/blob/5.4/src/Illuminate/Foundation/Testing/TestResponse.php#L363 - Tim Ogilvy
当结构不匹配时,测试框架不会显示不匹配的响应。我该如何访问它? - Onur Demir
1
对象数组中只有一个属性怎么办?你的解决方案对我很有用,但是它会在这种情况下引发错误 => ['data' => ['*' => [name]]]。这是一个错误,而不是失败,并且它说:PHPUnit\Framework\Assert::assertArrayHasKey()的第二个参数(无值)必须是数组或ArrayAccess。添加另一个属性后,错误消失了! - Khalil Laleh
1
对于任何想知道文档中是否有相关内容的人,实际上该内容已经在文档中了:https://laravel.com/docs/8.x/http-tests#assert-json-structure - mending3

3

我认为你应该使用:

 $response->assertJsonStructure([
    'status',
    'message',
    'data' => [
      [ // change here
        'id',
        'name',
        'email',
        'created_at',
        'updated_at',
        'user_id'
      ] // change here
    ]
  ]);

1
你说得对,但那只匹配了data数组中的一个对象。我已经解决了这个问题并在下面发布了解决方案。谢谢。 - Farooq Ahmed Khan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接