DEV Community

Cover image for Tips for testing with Laravel.
Ariel Mejia
Ariel Mejia

Posted on • Edited on

Tips for testing with Laravel.

Hi here a few tips to work on testing with Laravel, this post will be always on updating to grow.

Get form request/request validate errors as JSON for an API

Use the testCase method "json()"

$this->json('post', '/api/any', ['key' => 'value']);
Enter fullscreen mode Exit fullscreen mode

If you are making an ajax or fetch request the errors will be displayed as json by default, to tests this validation errors just use the "json()" method.

Create a Request class

This is particularly helpful if you are using dependency injection.

  • To create a request class and add params
$request = new \Illuminate\Http\Request();

$request->replace([
    "name"  => "John Doe",
    "email" => "john@doe.com",
]);
Enter fullscreen mode Exit fullscreen mode
  • It works also for a form request class:
$request = new FormRequestCustomClass();
$request->replace([
    "name"  => "John Doe",
    "email" => "john@doe.com",
]);
Enter fullscreen mode Exit fullscreen mode

Read a JSON response content easy.

You can chain "json()" method with "getContent()" method that allow you to view the response content, typically a convention is to hold the response in a variable to make some assertions, in this case as you wish to view response in JSON format you can use "json_encode()" php native function to get a better readability:

$response = $this->json('get', '/api/anyendpoint');
dd(json_decode($response->getContent()));
Enter fullscreen mode Exit fullscreen mode

It works for other methods to make a request like "get()", "post()", "put()", "delete()", but it has more sense in "json()" method because it returns a JSON.

Another way to inspect the response is with the method "dump":

$response->dump();
Enter fullscreen mode Exit fullscreen mode

Testing redirects

Typically in your controller you could return a redirect response in different ways:

return redirect('/users'); // case 1 not the best approach
return redirect->to('/users'); // case 2 still not the best
return redirect()->route('users); // case 3 a good practice
return redirect()->back(); // case 4 if your previous endpoint was "/users" this is fine
Enter fullscreen mode Exit fullscreen mode

Well, to test the redirect in many cases you can do something like:

$response->assertRedirect('/users'); // this works for case 1, 2, 3
$response->assertRedirect(route('users')); // this works for case 1, 2, 3
Enter fullscreen mode Exit fullscreen mode

As you can see the only method that cant be tested easily is the one that use the helper "back()", Laravel can test the "redirect" method if this add a explicit route, so the 4 case only will work by testing only the redirect status, like:

$response->assertStatus(302);
$response->assertRedirect();
Enter fullscreen mode Exit fullscreen mode

This maybe is not a granular test because we are only testing that a redirect is being executed, but this applies when you need to use the "back()" helper that is particularly useful in some situations.

Count items from a JSON response:

In any response you can return a json if this is a collection or a resource collection like:

$users = User::all();
// or
$users = UserResource::collection(User::all());
// or
$users = new UserResourceCollection(User::all());
Enter fullscreen mode Exit fullscreen mode

The Json response would return a nested items one for every user in the collection:

{
    "data": {
        {
            "name": "John Doe",
            "email": "john@doe.com"
        },
        {
            "name": "Anne Doe",
            "email": "anne@doe.com"
        },
        {
            "name": "Marie Doe",
            "email": "marie@doe.com"
        },
    }
}
Enter fullscreen mode Exit fullscreen mode

Then probable you would like to assert the total of items inside the data, well this is a very useful tip, the Laravel response has a method JsonCount() method, this would help to count the items in a JSON response:

If is an eloquent collection:

$response->assertJsonCount(5);
Enter fullscreen mode Exit fullscreen mode

If is a resource collection:

$response->assertJsonCount(5, 'data');
Enter fullscreen mode Exit fullscreen mode

Why add data? because the resources return all data formatted as you wish in a JSON with a 'data' key, so it will count the items (users) inside the data key.

Test API endpoints:

The rest standard requires to get data as:

fetch.get('/endpoint')
    .then(response => {
        const data = response.data
    })
Enter fullscreen mode Exit fullscreen mode

Usually the structure of any request requires a response object with data property, but Laravel resources add another data property to the response, to remove this other property and stay with API REST standard, Laravel provides a method to remove this other property, "withoutWrapping":

return new UserResource(User::first())->withoutWrapping();
Enter fullscreen mode Exit fullscreen mode

Thanks for reading, you are welcome to add comments to add more test tips!

Top comments (0)