0

I have a working api only application.

I am required to write a test decided to use laravel's phpunit test. This simple app allows only authenticated users can store, update or delete a book. Everyone else (authenticated or not) can retrieve a list of all books or view details of one book.

For my books test, I have written a test that first creates a user then a random token for the user. Then the token is passed using withHeaders when posting a new book record

class BooksTest extends TestCase
{
    public function test_onlyAuthenticatedUserCanAddBookSuccessfully()
    {
        $user = factory(User::class)->create();
        $token = str_random(10);
        $book = factory(Book::class)->create();

        $response = $this->withHeaders(['Authorization' => "Bearer $token"])
            ->json('POST', '/api/books', [
                'title' => 'book post',
                'author' => 'post author'
            ]);

        $response->assertStatus(201);
    }
}

Here I am using the default Laravel 5.6 UserFactory and my own BookFactory

$factory->define(Book::class, function (Faker $faker) {
    return [
        'title'     => $faker->sentence,
        'author'    => $faker->name,
        'user_id'   => 1
    ];
});

$factory->define(Rating::class, function (Faker $faker) {
    return [
        'user_id'   => 1,
        'book_id'   => mt_rand(1, 2),
        'rating'   => mt_rand(1, 5)
    ];
});

When I run the test, it fails and I get 401 instead of 200 which means the user is unauthorized.

I have a feeling that I have probably not set the $user in my test properly to be used during POST but I am not sure and really need help to get it right.

6
  • 1
    Hey, the token could not be some random strings, which approch do you use for authenticate users in your api? Commented Sep 28, 2018 at 7:38
  • I am using Passport for authentication process. How do I implement authentication in my test then? Commented Sep 28, 2018 at 7:40
  • 2
    I was using "JWT" before but take a look at this section: laravel.com/docs/5.7/passport#testing Commented Sep 28, 2018 at 7:41
  • @Nevo What does the second argument being the array of scopes that should be granted to the user's token mean? Looking at my code, I don't understand how I will use it during POST but using it to create a user is quite straight forward Commented Sep 28, 2018 at 7:53
  • The secoend parameter is the scope. I guess if you dont know about it just dont pass secoend argument. and in your code just remove the header from the request and set the passport code just before the request. I guess this will work fine Commented Sep 28, 2018 at 8:02

2 Answers 2

1

you can send headers in the fourth params of json() method as

$response = $this->json('POST', '/api/books', [
            'title' => 'book post',
            'author' => 'post author'
        ],['Authorization' => "Bearer $token"]);

since json method itself has provision to pass headers

or you can use post() method as

 $response = $this->post('/api/books', [
            'title' => 'book post',
            'author' => 'post author'
        ],['Authorization' => "Bearer $token"]);

Try this instead hope this solves your issues

Sign up to request clarification or add additional context in comments.

1 Comment

I understand I can send the headers as json() params and can do it too using withHeaders, however creating a token like this $token = $user->createToken('bookstore')->accessToken; and passing it inside the json() params returned this error There was 1 error: 1) Tests\Feature\BooksTest::test_onlyAuthenticatedUserCanAddBookSuccessfully ErrorException: Trying to get property 'client' of non-object
0

Not sure how authentication is hooked on your application, but you could try this:

...

$this->actingAs($user)
    ->jsonPost('/api/books', [
        // ...  
    ]);

$response->assertStatus(201);

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.