camcam
camcam

Reputation: 2625

Laravel unit testing function seeJsonStructure not working as expected

Laravel docs give an example of using function seeJsonStructure in PHPUnit testing:

  public function testBasicExample() {
    $this->get('/user/1')
      ->seeJsonStructure([
        'name',
        'pet' => [
          'name', 'age'
        ]
      ]);
  }

In my case, it seems that this function doesn't work as it's written in the docs. This is working for me:

public function testShow() {
    $this->get('api/mymodel/1');
    $this->seeJsonStructure([[
      'id',
      'name'
    ]]);
  }

The structural difference is the double square brackets instead of single. If I use it with single brackets as non-nested array, there is an error: "Failed asserting that an array has the key 'id'."

My controller is simple:

  public function show($id)
  {
    $items = MyModel::orderBy('name', 'ASC')
      ->where('id', '=', $id)
      ->get();
    return json_encode($items);
  }

I tried testing it also without json_encode in controller (returning just $items), but it was the same (worked only with double brackets)

I'd like to know whether it's a typo in the docs, or my controller is not returning what normally a controller should return as json api.

Upvotes: 0

Views: 2656

Answers (1)

tkausl
tkausl

Reputation: 14269

or my controller is not returning what normally a controller should return as json api.

Your controller is not returning what the controller in the docs-example is returning, yes. You're not returning a single model but a array of models with a single entry, therefore the array in array. The ->get() gets all entries which fit the requirements (the where-condition), which is only one, but you only expect a single one, so you should use ->firstOrFail() which gets a single one or fails if there is none (which automatically shows the 404-error).

Also, your order-by is pretty useless and you could (if you use laravel 5.2) rewrite your controller like this:

public function show(MyModel $model)
  {
    return $model;
  }

which does essentially the same.

Upvotes: 2

Related Questions