GimmeMylanta's avatar

Returning a generated token in a test

Hey Guys,

Im trying to write a test to check if a user gets successfully logged into our system

For some reason, its not seeing the token generated by the login endpoint.

I want to assert 3 things in my test.

  1. That the success flag is true .. This is currently working
  2. The message is set .. This is currently working
  3. The token gets returned .. This is the bit that i cant seem to get going.

My test is as follows;

public function it_logs_a_user_in()
{
    $user = factory(User::class)->create([ 'password' => Hash::make('foobar') ]);
    $payload = [ 'email' => $user->email, 'password' => 'foobar' ];

    $response = $this->json('POST', '/api/login', $payload);
    $response->assertStatus(200)
    ->assertJsonFragment([
        'success' => true,
        'message' => 'Yehhh Boiiiii'
    ]);
}

Looking at the response in Postman, i get the following;

{
    "success": true,
    "message": "Yehhh Boiiiii",
    "data": {
        "token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwOlwvXC9qb2JtYW5oZWxpb3MudGVzdFwvYXBpXC9hcGlcL2xvZ2luIiwiaWF0IjoxNTM5MzIyODcyLCJleHAiOjE1MzkzMjY0NzIsIm5iZiI6MTUzOTMyMjg3MiwianRpIjoiaXpQc2pvM0QxNm1SZ0VlayIsInN1YiI6MSwicHJ2IjoiMjNiZDVjODk0OWY2MDBhZGIzOWU3MDFjNDAwODcyZGI3YTU5NzZmNyJ9.ny4BKt0gcUCDiQ1a5bvsfwvcQfdV3nEPZAWVzBvziHo"
    }
}

Whatever i do, i cant seem to get the token returned.

Any help would be grand :)

0 likes
17 replies
D9705996's avatar

Have you tried dumping the response to see what it contains in your test as you postman output looks correct?

$response = $this->json('POST', '/api/login', $payload);
dd($response->toArray());

If you are seeing the token I would add a test for

->assertJsonCount(1, 'data.token');

You might need to tinker with the last argument depending on the output of the dd()

GimmeMylanta's avatar

@D9705996 I get the following error

BadMethodCallException: Method Illuminate\Http\JsonResponse::toArray does not exist.
GimmeMylanta's avatar

@D9705996 thats ok .. This is what i am getting using dd($response)

+original: array:3 [
    "success" => true
    "message" => "Yehhh Boiiiii"
    "data" => array:1 [
        "token" => "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwOlwvXC9sb2NhbGhvc3RcL2FwaVwvbG9naW4iLCJpYXQiOjE1MzkzMzM0NjMsImV4cCI6MTUzOTMzNzA2MywibmJmIjoxNTM5MzMzNDYzLCJqdGkiOiJscTNMVE00Q2FIbkJiUTlUIiwic3ViIjoxLCJwcnYiOiIyM2JkNWM4OTQ5ZjYwMGFkYjM5ZTcwMWM0MDA4NzJkYjdhNTk3NmY3In0.2ufSUEmW6FwxirRHrPU5tyb-Y9zrBss4ap0oIHxny2Y"
    ]
]

The token is there, but I just cant seem to get it into the assert statement

D9705996's avatar

You need a second assertion as you don't know what the value of the token will be.

Try ->assertJsonCount(1, 'data.token');

GimmeMylanta's avatar

@D9705996 damn, now im getting the following;

PHPUnit\Framework\Exception: Argument #2 (No Value) of PHPUnit\Framework\Assert::assertCount() must be a countable or iterable

My whole test is as follows;

public function it_logs_a_user_in()
{
    $user = factory(User::class)->create([ 'password' => Hash::make('foobar') ]);
    $payload = [ 'email' => $user->email, 'password' => 'foobar' ];

    $response = $this->json('POST', '/api/login', $payload);
    $response->assertStatus(200)
        ->assertJsonFragment([
            'success' => true,
            'message' => 'Yehhh Boiiiii'
        ])
        ->assertJsonCount(1, 'data.token');
}
tykus's avatar

You can assert that there is a token key in the json structure:

$response->assertJsonStructure([
    'success',
    'message',
    'data' => [
        'token'
    ]
]);
D9705996's avatar

@chris1981 - I often just convert the json response to an array/collection then use native PHPUnit assertions

$response = json_decode($this->json('POST', '/api/login', $payload)->getContent());
$this->assertNotNull($response['data']['token']);

tykus's avatar

No. But if you really wanted to, you could now check that there is a token using:

$this->assertNotNull(
    json_decode($response->getContent()['data']['token'])
);

In combination, with the structure assertion above, you have done as much as you can barring a regex on the token value

GimmeMylanta's avatar

@D9705996 Sorry to be a pain, but thats also erroring out.

ErrorException: json_decode() expects parameter 1 to be string, object given

@tykus im also getting an error from this

ErrorException: Illegal string offset 'data'
D9705996's avatar

I wouldn't bother trying do a regex on the token value. I would have a second test that gets a token then uses it and assert that you get the expected behaviour with a valid token.

D9705996's avatar
D9705996
Best Answer
Level 51

Not doing well today, I missed getContent()...


$response = json_decode($this->json('POST', '/api/login', $payload)->getContent());
$this->assertNotNull($response['data']['token']);

tykus's avatar

I missed true as second argument to json_decode so that you are dealing wiuth a nested array.

$responseData =  json_decode($response->getContent(), true);
$this->assertNotNull(
   $responseData['data']['token'])
);

I wouldn't regex the token either, my point was that you are doing as much as is reasonable already if you know you are getting a token and it is not null

1 like
GimmeMylanta's avatar

Thanks guys, thats worked now :)

Much appreciated for all your help, sorry about the back and forth.

Please or to participate in this conversation.