How To Use PHPUnit With Slim Framework 3
How To Use PHPUnit With Slim Framework 3
How To Use PHPUnit With Slim Framework 3
md 1/8/2023
Original POST
In order to fulfill one of the requirements for becoming a PHP web developer at Andela, we are required to
write an API service for emojis using Slim framework. After reading a lot of blogs and going through the
official documentation on the website, I set out to build the app as required.
But there was a problem: I needed to be able to test my app and all the tutorials I’ve read did not introduce
me to testing Slim apps. When I googled for answers on how to test Slim apps, I found hints and approaches
for writing testable apps, but nothing that was detailed enough for me to understand how to test my unbuilt
app.
Note: Writing testable apps with good test cases is a core requirement at Andela. Your App is not good
for review if you have not written tests.
Below, I’ll demonstrate how you can test your apps written using Slim framework using a very simple example.
In this tutorial, we will be writing an API that sends simple responses to various requests on a Todo object.
App Setup
Make and change our current directory to our Todo API folder
Create a composer file for the project For this project, this is the content our base composer file.
{
"name": "pyjac/slim-todo",
"authors": [
{
"name": "Pyjac",
"email": "pyjac@pyjac.com"
}
],
"require": {}
}
1 / 11
How to Use PHPUnit With Slim Framework 3.md 1/8/2023
This installs composer and its dependencies and inside the vendor folder and updates our composer.json file
to include slim as a dependency for the project.
Following best practises, we create a folder, public, a simple file, index.php, to house our setup code.
<?php
use \Psr\Http\Message\ServerRequestInterface as Request;
use \Psr\Http\Message\ResponseInterface as Response;
require '../vendor/autoload.php';
$app = new \Slim\App;
$app->get('/', function (Request $request, Response $response) {
$response->getBody()->write("Hello, Todo");
return $response;
});
$app->run();
The above is just a simple route definition for the / or index route.
Good!!!
Routes
Like I said earlier, this project is meant to create a very Todo API with simple responses and write basic tests
for the endpoints
Request Type: GET Endpoint: /todo Status: 200 Response: “Hello, Todo” Request Type: GET Endpoint:
/todo/:id Response status: 200 or 404 Response: “Todo :id” or “Todo Not Found” Request Type: POST, PUT,
PATCH Endpoint: /todo/:id Response status: 200 or 404 Response: “Todo :id, updated successfully” or “Todo
2 / 11
How to Use PHPUnit With Slim Framework 3.md 1/8/2023
Not Found” Request Type: DELETE Endpoint: /todo/:id Response status: 200 or 404 Response: “Todo :id,
deleted successfully” or “Todo Not Found”
<?php
require '../vendor/autoload.php';
function todoIdValid($id)
{
return (int)$id && $id > 0 && $id <= 10;
}
$app->group('/todo', function () {
$this->map(['GET'], '', function (Request $request, Response $response) {
return $response->withJson(['message' => 'Hello, Todo']);
});
3 / 11
How to Use PHPUnit With Slim Framework 3.md 1/8/2023
});
});
$app->run();
{
"name": "pyjac/slim-todo",
"authors": [
{
"name": "Pyjac",
"email": "oyebanji.jacob@andela.com"
}
],
"require": {
"slim/slim": "^3.0"
},
"require-dev": {
"phpunit/phpunit": "5.4.*"
}
}
Then, we run
composer update
mkdir test
In the test directory, create a new file named TodoTest.php and copy this as its content
<?php
}
}
Let’s run PHPUnit against TodoTest.php to ensure we have the correct setup
./vendor/bin/phpunit ./test/TodoTest.php
This was the first question I pondered over while setting out for my project.
But there is an issue with our current app setup. For our app to be testable we need to get the instance of the
app before we call the run method which bootstraps the app for web requests.
First, let’s create a new folder, src, to house our app class.
mkdir src
Secondly, we create a new file, App.php, in src directory and move some part of our index.php code into it.
<?php
namespace Pyjac\TodoAPI;
class App
{
5 / 11
How to Use PHPUnit With Slim Framework 3.md 1/8/2023
/**
* Stores an instance of the Slim application.
*
* @var \Slim\App
*/
private $app;
$app->group('/todo', function () {
$todoIdValid = function ($id) {
return (int)$id && $id > 0 && $id <= 10;
};
});
});
$this->app = $app;
}
/**
* Get an instance of the application.
*
* @return \Slim\App
*/
public function get()
{
return $this->app;
}
}
Because of the new namespace, Pyjac, we just included in our app, we need to update our composer.json file
to inform composer on how to autoload files in the src directory.
{
"name": "pyjac/slim-todo",
"authors": [
{
"name": "Pyjac",
"email": "email@email.com"
}
],
"require": {
"slim/slim": "^3.0"
},
"require-dev": {
"phpunit/phpunit": "5.4.*"
},
"autoload": {
"psr-4": {
"Pyjac\\TodoAPI\\": "src"
}
}
}
composer dump-autoload
7 / 11
How to Use PHPUnit With Slim Framework 3.md 1/8/2023
<?php
require '../vendor/autoload.php';
// Run app
$app = (new Pyjac\TodoAPI\App())->get();
$app->run();
With this, we can now create an instance of our app and pass in test requests to the app to simulate API calls.
Let’s test GET request to the app. To do this, we make use of theSlim\Http\Environment class to mock HTTP
headers and build up the Request object from the headers using Slim\Http\Request.
<?php
use Pyjac\TodoAPI\App;
use Slim\Http\Environment;
use Slim\Http\Request;
Notice how we called $this->app->run(true). This tells Slim to run the app instance and instead of return
HTTP headers and echoing the body of the response it should return an object.
8 / 11
How to Use PHPUnit With Slim Framework 3.md 1/8/2023
./vendor/bin/phpunit ./test/TodoTest.php
Congrats, we’re just written our first API test that hits an endpoint in our app and validate the correctness of
the status code and the response body.
Note: You can use the same pattern for PUT and PATCH
<?php
use Pyjac\TodoAPI\App;
use Slim\Http\Environment;
use Slim\Http\Request;
10 / 11
How to Use PHPUnit With Slim Framework 3.md 1/8/2023
Check out Oyebanji’s Github repo to understand how he implemented Slim in his project.
11 / 11