Warm tip: This article is reproduced from serverfault.com, please click

Why is a request returning forbidden only in PHPUnit testing?

发布于 2020-03-30 09:27:45

I'm having a problem with a test class in a Laravel 6 project. The following test fails because the returned response is 403 forbidden rather than a view. However, I can only reproduce this in tests - in the main application it returns the view as expected. Has anyone experienced anything similar or can see anything obviously wrong in the below?

ProductTest.php

public function testUsersCanViewTheirOwnProducts(){

        $user = Factory(User::class)->create();
        $product = Factory(Product::class)->create(['user_id'=>$user->id]);

        $this->actingAs($user);
        $response = $this->get(route('show_product',['product'=>$product->id]));

        $response->assertViewIs('products.show'); //Fails not a view (403 forbidden when response dumped)
        $response->assertViewHas('product',$product);

    }

Dumping $user->id and $product->id returns 1 for both as expected.

ProductController.php

public function __construct()
    {
        $this->authorizeResource(Product::class, 'product');
    }

//...

public function show(Product $product)
    {
        return view("products.show",['product'=>$product]);
    }

ProductPolicy.php

public function view(User $user, Product $product)
{
    return $user->id === $product->user_id;
}

testing.env

//identical to .env apart from
TELESCOPE_ENABLED=false
DB_DATABASE=subscribe_test

routes/web.php

Route::get('/manage/products/{product}','ProductController@show')->middleware('auth')->name('show_product');

I have cleared all caches with no effect. The resource returns 403 in PHPUnit tests and 200 in the application. What am missing?

Questioner
Rory
Viewed
0
Rory 2020-03-30 17:42:52

I have achieved the expected response in the test by editing my phpunit.xml file, which it turns out was overriding my .env.testing.

Removing these two lines gives the expected behaviour.

<server name="DB_CONNECTION" value="sqlite"/>
<server name="DB_DATABASE" value=":memory:"/>

Allowing my expected .env.testing to give:

DB_CONNECTION=mysql
DB_DATABASE=subscribe_test

However I don't see why this would fail on SQLLite? Especially when the values for comparing the IDs both dump the expected values.