Laravel Unit Testing Comprehensive Guide for Api Endpoints

Ariful Islam
4 min readJun 14, 2023

--

Introduction: Unit testing is an integral part of software development, ensuring that individual components of an application function as expected. When it comes to Laravel API development, unit testing plays a crucial role in maintaining code quality and preventing regressions. In this blog post, we will dive into the world of unit testing Laravel API endpoints, exploring best practices and demonstrating how to create effective test cases using Laravel’s testing framework.

Prerequisites: Before we proceed, make sure you have a basic understanding of Laravel and its testing framework. Familiarity with PHPUnit, Laravel’s default testing tool, will be beneficial. Additionally, setting up a Laravel project and its associated testing environment is a prerequisite for following along with the examples provided in this blog.

Setting Up Your Testing Environment: To begin, ensure that your Laravel project has PHPUnit installed. You can install PHPUnit globally using Composer by running the following command:

composer global require phpunit/phpunit

Once PHPUnit is installed, Laravel provides a TestCase class that extends PHPUnit’s base TestCase. This class is an excellent starting point for your API endpoint unit tests. You can find it at tests/TestCase.php. By default, Laravel ships with a tests/Feature directory where you can place your endpoint tests.

Understanding API Endpoint Testing: When testing API endpoints, we typically focus on verifying two aspects: the response format and the underlying logic. Laravel provides a suite of helpful methods and assertions to simplify this process.

  1. Response Format Testing: When testing API endpoints, it’s crucial to verify that the response format matches your expectations. For example, you may want to ensure that a JSON response contains specific keys or follows a specific structure. Laravel’s testing framework provides methods like assertJsonStructure() and assertJson() that simplify response format testing.

2. Underlying Logic Testing: API endpoints usually encapsulate some business logic, such as data validation, database interactions, or external service calls. To test this logic, you can use Laravel’s testing framework to mock dependencies, such as databases or third-party APIs, and assert that the expected behavior occurs. Laravel’s Mockery library is a powerful tool for creating mocks and expectations.

Creating API Endpoint Unit Tests: Let’s walk through an example of testing a simple API endpoint using Laravel’s testing framework:

<?php

namespace Tests\Feature;

use Tests\TestCase;
use Illuminate\Foundation\Testing\RefreshDatabase;

class UserTest extends TestCase
{
use RefreshDatabase;

public function testGetUserEndpoint()
{
// Arrange
$user = factory(\App\Models\User::class)->create();

// Act
$response = $this->get('/api/users/' . $user->id);

// Assert
$response->assertStatus(200)
->assertJsonStructure(['id', 'name', 'email']);
}

/**
* Test storing an API user.
*
* @return void
*/
public function testStoreApiUser()
{
// Generate new data for creating the user
$userData = [
'name' => 'John Doe',
'email' => 'john.doe@example.com',
'password' => 'secret',
];

// Send a POST request to store the user
$response = $this->post('/api/users', $userData);

// Assert that the request was successful (status code 201)
$response->assertStatus(201);

// Assert that the user was stored in the database with the provided data
$this->assertDatabaseHas('users', [
'name' => $userData['name'],
'email' => $userData['email'],
]);
}

/**
* Test updating an API user.
*
* @return void
*/
public function testUpdateApiUser()
{
// Create a user
$user = User::factory()->create();

// Generate new data for updating the user
$newData = [
'name' => 'John Doe',
'email' => 'john.doe@example.com',
];

// Send a PUT request to update the user
$response = $this->put('/api/users/' . $user->id, $newData);

// Assert that the request was successful (status code 200)
$response->assertStatus(200);

// Assert that the user was updated with the new data
$this->assertDatabaseHas('users', [
'id' => $user->id,
'name' => $newData['name'],
'email' => $newData['email'],
]);
}

/**
* Test deleting an API user.
*
* @return void
*/
public function testDeleteApiUser()
{
// Create a user
$user = User::factory()->create();

// Send a DELETE request to delete the user
$response = $this->delete('/api/users/' . $user->id);

// Assert that the request was successful (status code 204)
$response->assertStatus(204);

// Assert that the user no longer exists in the database
$this->assertDatabaseMissing('users', [
'id' => $user->id,
]);
}
}

In this example, we’re using Laravel’s testing framework to create a test case for deleting an API user. We first create a user using a factory. Then, we send a DELETE request to the appropriate API route (/api/users/{id}) with the user's ID. We assert that the request was successful (status code 204) and that the user no longer exists in the database.

Remember to update the namespace, class name, and any other relevant details based on your project’s structure. Additionally, ensure you have the necessary dependencies and testing configurations in place to run the tests successfully.

--

--

Ariful Islam

Software Engineer. Working on PHP, Laravel, CI, CakePhp, API. Open Source contributor, Cloud Expert, Project Consultant; https://linkedin.com/in/arif98741