Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

Steady-Entertainment's avatar

Confusion / Explanation / Tutorial for JSON in testing with PHP unit

Hey guys I am a bit confused and cannot really understand the overall concept of the following commands.

When do I use which one and what does it actually do?

I understand what JSON is but I do not understand the concept of the following methods and how and when to use them.

getJson()
expectJson()
json()

Especially when it comes to testing and controllers in laravel.

A brief high level description to grasp my head around the concept should be sufficient for this matter.

A small example would be on top. :D

I searched the internet but there isn't an answer to this specific question.

Sure I can look up the methods in the php doc, but my question is more a general usage question and how it works with laravel testing.

0 likes
8 replies
Nakov's avatar
Nakov
Best Answer
Level 73

So getJson() is used for testing, when you want to make a GET request to an endpoint, and the response you expect to be JSON

https://laravel.com/docs/master/http-tests#testing-json-apis

Then expectsJson() is actually wantsJson() and it is used on the request itself, you can use it in your controller, if you want to handle different response, for example if from your test you use the getJson() your controller should handle that, but you might want to also return view from the controller, so you will do something like this:

public function show(Request $request, User $user)
{

    if($request->wantsJson())
    {
        return response()
            ->json(['user' => $user])
    }

    return view('users.show', compact('user'));
}

And you see above why the json() is used. So the response is JSON formatted.

Steady-Entertainment's avatar

THX for your answer one last question for today.

How do I know if I expect JSON from my endpoint or just a collection?

Nakov's avatar

For the JSON, if you request a proper JSON then the content-type for the request will be application/json that's how it will know if the response should be JSON.

Steady-Entertainment's avatar
if($request->wantsJson())
    {
        return response()
            ->json(['user' => $user])
    }

I dont understand this something is blocked in my brain how can a request want JSON?

If i replace getJson with get in my tests it still works the same way ....

I understand how you can convert a collection to JSON

but I cannot understand:

How a response can want or expect JSON

or

How a get request can be a getJson get request ..

I am still confused about this ... really sorry

Nakov's avatar

@steady-entertainment if you use a JSON get request, this is the underlying code:

public function json($method, $uri, array $data = [], array $headers = [])
    {
        $files = $this->extractFilesFromDataArray($data);

        $content = json_encode($data);

        $headers = array_merge([
            'CONTENT_LENGTH' => mb_strlen($content, '8bit'),
            'CONTENT_TYPE' => 'application/json',
            'Accept' => 'application/json',
        ], $headers);

        return $this->call(
            $method, $uri, [], [], $files, $this->transformHeadersToServerVars($headers), $content
        );
    }

see the Content-Type there, it is in the header.

This is the wantsJson implementation:

public function wantsJson()
    {
        $acceptable = $this->getAcceptableContentTypes();

        return isset($acceptable[0]) && Str::contains($acceptable[0], ['/json', '+json']);
    }

it checks for that content type.

If you do a normal GET request the content type is text/html or form-data something like that, more on this here:

https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Type

so you should have this:

if($request->wantsJson())
    {
        return response()
            ->json(['user' => $user])
    }

return view();

if the request is not getJson then it will return a view, not the JSON response.

If you use IDE you can just click on the methods and see the underlying code.

Steady-Entertainment's avatar

this


/** @test */
     function a_user_can_request_all_replies_for_a_given_thread()
     {

         $thread = create('App\Thread');
         create('App\Reply', ['thread_id' => $thread->id], 11);

         $response = $this->get($thread->path() . '/replies');

         $this->assertCount(10, $response->json()['data']);
         $this->assertEquals(11, $response->json()['total']);
}

and this

/** @test */
     function a_user_can_request_all_replies_for_a_given_thread()
     {

         $thread = create('App\Thread');
         create('App\Reply', ['thread_id' => $thread->id], 11);

         $response = $this->getJson($thread->path() . '/replies')->json();

         $this->assertCount(10, $response['data']);
         $this->assertEquals(11, $response['total']);
}

makes no difference to me

Nakov's avatar

@steady-entertainment it will make no difference if in your controller you return the user directly, like this:

if($request->wantsJson())
    {
        return response()
            ->json(['user' => $user])
    }

return $user;

Why you are using json(); at the end of the getJson() request?

As I said it makes difference when you use it. You are either making an AJAX code and you want the result to be JSON data, or you are making a normal GET request, loading a view.

Please or to participate in this conversation.