pest: Using factories in beforeAll/afterAll hook throws InvalidArgumentException
Hey,
Reproducible with clean project:
laravel new pest-beforeAll
composer require pestphp/pest --dev --with-all-dependencies
composer require pestphp/pest-plugin-laravel --dev
php artisan pest:install
Refactor the default ExampleTest.php to Pest and try to create User factory in beforeAll/afterAll hook:
<?php
use App\Models\User;
use function Pest\Laravel\be;
use function Pest\Laravel\get;
beforeAll(function(){
be(User::factory()->create());
});
test('basic test', function(){
get('/')->assertStatus(200);
});
Run php artisan test and it will fail with:
When using beforeEach instead of beforeAll the tests pass. ✨
Sorry that this didn’t come with a pull request - haven’t tinkered with reflection that deep and I bet given that it’s reproducible someone from the core contributors will have easier time fixing this. Alternatively if someone could provide some pointers as to what might be the cause I can take a look and try to figure it out. 🤓
About this issue
- Original URL
- State: closed
- Created 4 years ago
- Reactions: 2
- Comments: 18 (7 by maintainers)
A very strange solution, making the use of Pest very questionable. How do I set up group of tests?
@ilyavaiser I agree with you, as I am having the same issue. I need to test a table sorting, and for each test case, I need to seed my DB again and again with the same data, which influences the performance of the test. In fact, it should be done only once.
@nunomaduro it doesn’t mention there the fact that the framework hasn’t booted and you can only run basic code. Would be a nice touch for new adopters who don’t know/haven’t used PHPUnit and jump right in to PestPHP. 🚀
I second the request. I’m starting using Pest too since yesterday and it take me a while to understand that the class isn’t instantiated during beforeAll() which i find it odd, so i thought i was doing something wrong.
So i think that beforeAl() should be instantiated after the class is initialized, it should be a good gain on performance time if we have to load the fixtures once for the class instead of each test.
Edit: im using Symfony and not Laravel
This is a known “issue”,
beforeAll/afterAllare called before (or after) the class has been instantiated (they are the equivalents of@beforeClassand@afterClassin PHPUnit). So the framework hasn’t been booted at that point. 👍🏻 In the meantime you need to usebeforeEach/afterEach. See https://github.com/pestphp/pest/issues/237 and https://github.com/pestphp/pest/issues/33#issuecomment-658022624. 🙂 I think that Nuno was thinking about a possible way of resolving this though. 🤔It’s not really an issue, just a lot of people seem to get confused with
beforeAll()/beforeEach()not working like howsetUp()andtearDown()work.I guess this is resolved now via: https://pestphp.com/docs/pest-spicy-summer-release#content-describe-blocks. 👏🏼
@nunomaduro it’s obvious from the previous comments and likes that a lot of devs want to be able to access framework functionalities, e.g factories, artisan commands, etc once before the whole test runs and hence access to the application’s booted state. Is there a way out to do this without having to repeat executions in the
beforeEachhook?I must admit that even I didn’t know about the
@beforeClassrestrictions because I hadn’t used them in Laravel. 😄That note seems Laravel specific.