How to Unit Test a Laravel API with the Pest Framework
Time to read: 6 minutes
Pest is a new PHP testing framework developed by Nuno Maduro. While Pest itself is built on top of PHPUnit, the popular and widely adopted PHP testing framework, Pest aims to provide a better experience for writing tests. The philosophy is simple. Keep the TDD experience simple and elegant by providing expressive interfaces.
In this tutorial, we’ll be looking at how to get started using Pest in a Laravel project. Using the test-driven approach, we’ll be building a simple Todo application that allows you to create, edit, update and delete tasks.
Technical requirements
- PHP version 8.3 or higher (ideally 8.4)
- Laravel 12
- Composer installed globally
- A basic understanding of automated software testing, such as TDD (Test-driven Development)
Set up Laravel
There are different ways to set up a new Laravel project. You can do so via the Laravel installer or by using Composer. For the sake of this tutorial, we’ll be using Composer.
Run the following commands in your terminal to create a new Laravel project and to change into the new project directory:
Install Pest
Now that we’ve set up a new Laravel project, there are a couple of additional steps we need to carry out to set up Pest with Laravel. First, remove PHPUnit and install Pest by running the following commands:
Next, we’ll be installing the Pest Plugin for Laravel. To do that, run the following command:
Then, once the plugin has been installed, run the following command to initialize Pest with the project. This command will create a configuration file named Pest.php in the project's top-level directory:
The Pest.php file is autoloaded automatically and serves as an ideal place to recursively bind helper classes and traits to your tests.
Laravel comes bundled with some example test files based on PHPUnit. Let’s change those tests to make use of Pest instead. Head over to the tests/Feature directory and take a look at the ExampleTest.php file. Here’s what it currently looks like:
To migrate this test to the corresponding Pest implementation, replace the content of the file with the following code:
Much cleaner, right? We’ve reduced this ExampleTest file from about 20 lines of code to just two, while testing the exact same thing and producing the same result. That is, it visits the root URL at ‘/’ and asserts that an HTTP status code of 200 OK is returned.
Pest provides two functions for writing tests — test()
and it()
. Both functions accept a test description as the first argument and a closure that contains the test expectations as the second argument. They share the same syntax and behavior and you’re free to use either one you find fitting. I personally prefer using it()
since they make your test cases read like a complete sentence.
Similarly, let’s make the ExampleTest.php file located in the tests/Unit directory use Pest as well. Replace the contents of the file with the following code:
Next, use the following command to run the test suite:
All tests should be passing as seen in the image below.


Create the Todo model, migration and controller
Our application is going to have a single model called "Todo". Laravel provides a handy command for generating a model, migration, and controller for an entity all at once. To do that run the following command:
The command created three files:
- A migration file named [TODAYSDATE]_create_todos_table.php in database/migrations
- A model file named Todo.php in app/Models
- A controller file named TodoController.php in app/Http/Controllers
Next, update the migration file's up()
method to match the following code:
Each todo task will have a name
attribute as well as a boolean completed
attribute, with a default value of false
.
Next, edit the App/Models/Todo.php file with the following code:
Here, we assign the name
and completed
attribute of the model to be mass-assignable.
Create the Todo factory
Laravel model factories provide a convenient way of seeding the database with data. This is very useful when it comes to testing.
Run the following command to create a factory class for the Todo model:
This creates TodoFactory.php for us in the database/factories directory.
Now, edit the definition()
method within the file to return an array similar to the one below:
The definition()
method returns the default set of attribute values that should be applied when creating a model using the factory.
With all of the Todo model setup finished, you next need to run the database migrations to update the database, by running the command below.
Write the tests
Now that we’ve done all the necessary setup, we can get started with writing the tests. These tests are required to have a functioning application and will provide the corresponding implementation to make sure all the tests pass.
Run the following Pest command to create a unit test file:
This will create TodoTest.php in the tests/Unit directory. Replace the file’s code with the following code:
At the top of the file, the uses()
method binds the TestCase
class and the RefreshDatabase
trait to the current test file. The base TestCase
class is provided by Laravel and provides helper methods for working with the framework while testing. The RefreshDatabase
trait takes care of migrating and resetting the database after each test so that data from a previous test does not interfere with subsequent tests.
Now, let’s go over what each test is doing:
- it("does not create a todo without a name field"): Laravel provides several helpers for testing JSON APIs and their responses. Here we make use of the
postJson()
helper to make a POST request to theapi/todos
endpoint passing in an empty array. Next, theassertStatus()
method on the returned response ensures that an HTTP status code of 422 Unprocessable Content should be returned. This test ensures that a name field will always be present on the request payload. - it("can create a todo"): This test ensures that a todo is created on making a POST request to the api/todos endpoint. We assert that an HTTP status code of 201 Created is returned and that the database actually contains the todo using the
assertDatabase()
method. - it("can fetch a todo"): This test checks to see that a particular todo task can be fetched using the ID. Using the
create()
method on the Todo Factory, a todo task is created and stored in the database. Similarly, we assert that the status code returned is 200 OK. TheassertJson()
method converts the response to an array and verifies that the given array exists within the JSON response that will be returned by the application. - it("can update a todo"): This test ensures that a todo task can be updated and that the updated task can be found in the database.
- it("can delete a todo"): This test ensures that a todo task can be deleted and verifies that the total number of tasks contained within the database is zero.
To run the test suite, run the following command:
The test suite should be failing since we have not implemented any of the features, as you can see in the screenshot below.


Build the Todo application
Let’s provide the corresponding implementation of the tests we’ve written so far. Head over to the TodoController.php file in the app/Http/Controllers directory and replace the file’s code with the following code:
- The
create()
method creates a new todo task - The
show()
method returns a given task based on it’s ID - The
update()
method updates a todo task - The
delete()
method deletes a given todo task
Next, we need to add API routes. But, before we can do that, we need to create the API routes file (routes/api.php). To do that, run the following command.
During the installation, you'll be prompted as follows:
Answer this with either "yes" or just press Enter.
Now, with the API routes file created (routes/api.php), update the file to match the code below:
Now that we’ve provided all the corresponding implementations for the tests, we can go back to running our tests and they should all be passing now. Run the test suite again with the following command:
The terminal output should match the output in the screenshot below.


That's how to unit test a Laravel API with the Pest framework
In this tutorial, we’ve seen how to go about writing unit tests for a Laravel application using the Pest testing framework. This tutorial can serve as a great guide for getting started with Pest as well as unit testing a Laravel application.
Dotun Jolaoso can be found at https://dotunj.dev/, https://github.com/Dotunj, and https://twitter.com/Dotunj_.
Related Posts
Related Resources
Twilio Docs
From APIs to SDKs to sample apps
API reference documentation, SDKs, helper libraries, quickstarts, and tutorials for your language and platform.
Resource Center
The latest ebooks, industry reports, and webinars
Learn from customer engagement experts to improve your own communication.
Ahoy
Twilio's developer community hub
Best practices, code samples, and inspiration to build communications and digital engagement experiences.