Higher Order Tests

Overview

Pest also provides support for higher order tests, which are shortcuts for performing common actions while writing your tests.

The best way to think about this is: If you don't provide a closure, the chained methods are going to create a closure for you. Here is the most basic example:

1test('true is true')->assertTrue(true);

The code above is equivalent to:

1test('true is true', function () {
2 $this->assertTrue(true);
3});

Pest will properly delegate to any given method and its arguments of the test itself.

Sometimes, you'll need to access methods not available until runtime. Higher order tests provide the tap method, which receives a closure and executes the code inside:

1it('writes to the database after the command is run')
2 ->tap(fn() => $this->artisan('your-command'))
3 ->assertDatabaseHas('users', ['id' => 1]);

If you want to perform an expectation on a runtime value in higher order tests, you can pass a closure to the expect method:

1it('points to the correct URL')
2 ->expect(fn() => route('dashboard'))
3 ->toBe('http://example.com/dashboard');

The exact same rules apply to global functions like beforeEach or afterEach. Let's take a look at an example using the Laravel Framework:

1beforeEach()->withoutMiddleware();
2 
3it('has home')
4 ->get('/admin')
5 ->assertSee('Hello World');

Pest also provides support for higher order expectations when writing higher order tests:

1test('the user has the correct values')
2 ->expect(fn() => Auth::user())
3 ->first_name->toEqual('Nuno')
4 ->last_name->toEqual('Maduro')
5 ->withTitle('Mr')->toEqual('Mr Nuno Maduro');

Working with Datasets

When working with datasets, Pest allows you to access the dataset values in higher order tests when using the expect, and or tap methods:

1it('validates the user names')
2 ->with('badUsernames')
3 ->expect(fn($name) => ValidateUserName::isValid($name)) // We receive the data as a parameter to `expect`
4 ->toBeFalse();
5 
6it('inserts a user in the database')
7 ->with('users')
8 ->tap(fn($name, $email) => User::create(['name' => $name, 'email' => $email])) // You may receive multiple arguments
9 ->assertDatabaseHas('users', 1);

Next section: Custom Helpers →