Unit testing your API in Laravel

Unit testing your API in Laravel

Mark Scherrenberg
Aug 5, 2018 · 3 min read

So let’s say you’ve build an API, but want to take it a step further by testing it. Well, Laravel makes it very easy.

At first, let’s set-up a new Laravel enviroment. I’m using Laravel’s 5.6 version for this article.

After laravel is installed make sure phpunit is installed on your machine. You can install it here: https://phpunit.de/getting-started/phpunit-7.html.

After installing phpunit, enter the following command in your terminal pointing at your laravel’s project root directory.

phpunit

If every is set-up properly you should get something like:

PHPUnit 7.3.0 by Sebastian Bergmann and contributors...                                                                  2 / 2 (100%)Time: 1.12 seconds, Memory: 12.00MBOK (2 tests, 2 assertions)

Now head over to /.phpunit.xml and override the database connection and disable the APP_DEBUG configuration of the .env file. So phpunit will use sqlite. Add the following in the <php> section:

<env name="DB_CONNECTION" value="sqlite"/>
<env name="APP_DEBUG" value="false"/>

So it should look like this:

...
<php>
<env name="APP_ENV" value="testing"/>
<env name="BCRYPT_ROUNDS" value="4"/>
<env name="CACHE_DRIVER" value="array"/>
<env name="SESSION_DRIVER" value="array"/>
<env name="QUEUE_DRIVER" value="sync"/>
<env name="MAIL_DRIVER" value="array"/>
<env name="DB_CONNECTION" value="sqlite"/>
<env name="APP_DEBUG" value="false"/>
</php>
...

Let’s create a new Model called Post with:

php artisan make:model Post -c -m -f

Adding -c, -m, -f after the model name will also generate a controller, migration and factory file. Head over to the migration file and add a few lines at the up() method:

public function up()
{
Schema::create('posts', function (Blueprint $table) {
$table->increments('id');
$table->string('title');
$table->text('content');
$table->timestamps();
});
}

Then in /database/factories/PostFactory.php add a few lines:

<?phpuse Faker\Generator as Faker;$factory->define(App\Post::class, function (Faker $faker) {
return [
'title' => $faker->sentence,
'content' => $faker->paragraph
];
});

When the Post factory is set-up go to the Post model /app/Post.php and add protected fillable to be able to use the create method:

<?phpnamespace App;use Illuminate\Database\Eloquent\Model;class Post extends Model
{
protected $fillable = [
'title',
'content'
];
}

In /app/Http/Controllers/PostController.php and add some basic crud methods for testing purpose:

<?phpnamespace App\Http\Controllers;use App\Post;
use Illuminate\Http\Request;
class PostController extends Controller
{
public function index() {
return Post::all();
}

public function show(Post $post) {
return $post;
}
public function store(Request $request) {
$post = Post::create($request->all());
return response()->json($post, 201);
}
public function update(Request $request, Post $post) {
$post->update($request->all());
return response()->json($post);
}
public function delete(Post $post) {
$post->delete();
return response()->json(null, 204);
}
}
  • Index (Returns all posts)
  • Show (Returns a single posted based on the id in the parameter)
  • Store (Returns the created post with a 201 status code, meaning: ‘Content created’)
  • Update (Returns the updated post with the default 200 status code)
  • Delete (Returns null with a 204 status code, meaning: ‘No content’)

Read more about status codes: https://httpstatuses.com/

In /routes/api.php add some routes to use our controller:

  • Be aware that there is no authentication on any of the routes currently.
  • All routes in /api.php will be prefixed with /api
  • In the group I prefixed all underlaying routes with /posts. So for instance to request the first route, you would call: /api/posts

Then run the migration file using:

php artisan migrate

Laravel ships with two test classes located in /tests/Feature and /tests/Unit. We’ll start by editing /tests/TestCase.php to:

Use the following command to generate a new unit test file:

php artisan make:test PostTest --unit

Open the generated file /tests/Unit/PostTest.php and add the testing methods:

  • Every test has his own method prefixed with test, this is required for phpunit to find and use the test method.
  • We’re checking if the expected status codes are returned with assertStatus
  • With assertJson we’re testing if the JSON result matches our expectation.
  • In test_can_list_posts we’re removing all attributes of each post created so we’ll only have ‘id’, ‘title’ and ‘content’. And then we check that all items in the returned JSON array by the API contain ‘id’, ‘title’, ‘content’ by using assertJsonStructure.

To test, let’s run phpunit in the terminal:

phpunit

That’s it! It should pass all tests. Feel free to contact me if you have any questions or improvements, I’m happy to help.

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade