pestphp / pest

Pest is an elegant PHP testing Framework with a focus on simplicity, meticulously designed to bring back the joy of testing in PHP.
https://pestphp.com
MIT License
9.62k stars 358 forks source link

Higher order test does have access to the database #153

Closed roni-estein closed 4 years ago

roni-estein commented 4 years ago

When running code in the beforeEach function, the code the code is not run before higher order tests.

Here are some input output tests in a basic project

EXPECTED

beforeEach(function(){
    dump('hello');
});

it('runs before each')
    ->dd('there')
    ->assertTrue(true);

//OUTPUT
PHPUnit 9.2.6 by Sebastian Bergmann and contributors.

"hello"
"there"

Process finished with exit code 1
beforeEach(function(){
    (new BasicSetup)->run();
    dd(User::first());
});

it('runs before each')
    ->dd('there')
    ->assertTrue(true);

//OUTPUT
PHPUnit 9.2.6 by Sebastian Bergmann and contributors.

pp\User {#2427
  #fillable: array:3 [
    0 => "name"
    1 => "email"
    2 => "password"
  ]
  #hidden: array:2 [
    0 => "password"
    1 => "remember_token"
  ]
  #casts: array:1 [

...

Process finished with exit code 1

UNEXPECTED, expecting same output as the last test

beforeEach(function(){
    (new BasicSetup)->run();
//    dd(User::first());
});

it('runs before each')
    ->dd(User::first())
    ->assertTrue(true);

// OUTPUT
Testing started at 8:20 p.m. ...
/usr/local/bin/php /Users/xxxx/code/php/laravel/7.x/bga/vendor/pestphp/pest/bin/pest --teamcity --configuration /Users/xxxx/code/php/laravel/7.x/bga/phpunit.xml /Users/xxxx/code/php/laravel/7.x/bga/tests/Feature/Product/PriceListImporterTest.php --filter=/runs\sbefore\seach$/

   Error 

  Call to a member function connection() on null

  at vendor/laravel/framework/src/Illuminate/Database/Eloquent/Model.php:1342
    1338▕      * @return \Illuminate\Database\Connection
    1339▕      */
    1340▕     public static function resolveConnection($connection = null)
    1341▕     {
  ➜ 1342▕         return static::$resolver->connection($connection);
    1343▕     }
    1344▕ 
    1345▕     /**
    1346▕      * Get the connection resolver instance.

      +7 vendor frames 
  8   tests/Feature/Product/PriceListImporterTest.php:18
      Illuminate\Database\Eloquent\Model::__callStatic("first", [])

Process finished with exit code 1

FINAL SANITY TESTS

beforeEach(function () {
    (new BasicSetup)->run();
//    dd(User::first());
});

// I purposely left my own dd function in there so the code was identical
it('runs before each', function () {
    $this
        ->dd(User::first())
        ->assertTrue(true);
});

//OUTPUT
PHPUnit 9.2.6 by Sebastian Bergmann and contributors.

App\User {#2425
  #fillable: array:3 [
    0 => "name"
    1 => "email"
    2 => "password"
  ]
  #hidden: array:2 [
    0 => "password"
    1 => "remember_token"
  ]
  #casts: array:1 [

...

Process finished with exit code 1

Change to higher order beforeEach, no change in output

beforeEach(fn()=>  (new BasicSetup)->run());

tests/Pest.php

<?php

use Illuminate\Foundation\Testing\RefreshDatabase;

uses(Tests\TestCase::class)->in('Feature');

uses(RefreshDatabase::class)->in('Feature');

tests/TestCase.php has these 2 additional functions

public function dd($payload)
{
    dd($payload);
}

public function dump($payload)
{
    dump($payload);

    return $this;
}

if you need any further information to debug this or there is a critical error in what I'm doing please let me know. Thanks.

hackel commented 4 years ago

This looks like the expected behaviour to me. In your unexpected case, you're running User::first() right away instead of queuing it up in a closure to go in your testcase once the application is booted and beforeEach has run. If you update your dd method to accept a closure and dump the results, that should solve your problem.

it('runs before each')
    ->dd(fn () => User::first())
    ->assertTrue(true);