Skip to content
This repository has been archived by the owner on Dec 11, 2020. It is now read-only.

Testing Features and Jobs

Abed Halawi edited this page Sep 11, 2016 · 1 revision

Every generated Feature and/or Job will get a test class generated with it, acting as the unit test of the corresponding Feature/Job.

Preparation

  • Generate a Feature called ListUsers in an Api service
lucid make:feature api listUsers

This will generate two files:

  • src/Services/Api/Features/ListUsersFeature.php
  • src/Services/Api/Tests/Features/ListUsersFeatureTest.php

If we examine the test file we should see the following:

<?php
namespace App\Services\Api\Tests\Features;

use PHPUnit_Framework_TestCase as TestCase;
use App\Services\Api\Features\ListUsersFeature;

class ListUsersFeatureTest extends TestCase
{
    public function test_listusersfeature()
    {
        $this->markTestIncomplete();
    }
}

Before we start testing, we need to implement our Feature to know what we should be testing.

To list users using JSON we need to run two jobs:

  • Get users from database
  • Respond with a JSON including the list of users

It is now obvious that we need to generate a Job to get the users from the database so let's do that first, test it, and then come back to test our Feature.

Testing Jobs

Generate Job

lucid make:job user GetUsersFromDb
  • Open src/Domains/User/Jobs/GetUserFromDbJob.php to implement the job.

This Job is simple, it will use the User model to get all of the users:

In Lucid the base namespace for what Laravel provides as a framework is Framework

namespace App\Domains\User\Jobs;

use Framework\User;
use Lucid\Foundation\Job;

class GetUsersFromDbJob extends Job
{
    public function handle(User $user)
    {
        return $user->all();
    }
}

Test Job

src/Domains/User/Tests/Jobs/GetUserFromDbJobTest.php

Testing the Job is simply following these steps:

  • Mock Framework\User::all
  • Instantiate the Job
  • Call the Job's handle method passing the mocked model
namespace App\Domains\User\Tests\Jobs;

use Mockery as M;
use Framework\User;
use PHPUnit_Framework_TestCase as TestCase;
use App\Domains\User\Jobs\GetUsersFromDbJob;

class GetUsersFromDbJobTest extends TestCase
{
    public function test_getusersfromdbjob()
    {
        $mUser = M::mock(User::class);
        $users = ['user1', 'user2'];
        $mUser->shouldReceive('all')->once()->andReturn($users);

        $job = new GetUsersFromDbJob();
        $this->assertEquals($users, $job->handle($mUser));
    }
}
  • Run the test
phpunit --filter GetUsersFromDbJobTest
  • You should see:
PHPUnit 5.5.4 by Sebastian Bergmann and contributors.

.                                                                   1 / 1 (100%)

Time: 123 ms, Memory: 14.75MB

OK (1 test, 1 assertion)

With that we have created a Unit Test for our Job, which is how they are intended to be tested: In isolation, mocking their dependencies.

Testing Features

When it comes to testing Features, what we care about is the functionality, hence, a Functional Test is required for our Feature rather than a Unit Test.

Serve Feature

First, we need to expose our Feature through a controller and a route:

lucid make:controller api user

Will generate src/Services/Api/Http/Controllers/UserController.php where we'll serve the ListUsersFeature from the index method with:

// ...
use App\Services\Api\Features\ListUsersFeature;
// ...
public function index()
{
    return $this->serve(ListUsersFeature::class);
}

And in src/Services/Api/Http/routes.php add the following to the existing route group api

Route::get('/users', 'UserController@index');

Implement Feature

namespace App\Services\Api\Features;

use Illuminate\Http\Request;
use Lucid\Foundation\Feature;
use App\Domains\User\Jobs\GetUsersFromDbJob;
use App\Domains\Http\Jobs\RespondWithJsonJob;

class ListUsersFeature extends Feature
{
    public function handle(Request $request)
    {
        $users = $this->run(GetUsersFromDbJob::class);

        return $this->run(new RespondWithJsonJob($users));
    }
}

Test Feature

Testing the features involves three steps:

  • Generating database records
  • Issuing a request to the /api/users route
  • Asserting the returned JSON structure

In this setup we are using SQLite as a database, you may need to configure your preferred database in config/database.php

The test in src/Services/Api/Tests/Features/ListUsersFeatureTest.php will look like this:

namespace App\Services\Api\Tests\Features;

use TestCase;
use Framework\User;
use Illuminate\Http\Request;
use App\Services\Api\Features\ListUsersFeature;
use Illuminate\Foundation\Testing\DatabaseMigrations;

class ListUsersFeatureTest extends TestCase
{
    use DatabaseMigrations;

    public function test_listusersfeature()
    {
        factory(User::class, 3)->create();

        $response = $this->json('GET', '/api/users')
            ->seeJsonStructure([
                'data' => [
                    '*' => ['id', 'name', 'email']
                ]
            ]);
    }
}

Since we've used our RespondWithJsonJob it wraps the returned JSON structure within a data key.

Run Test

phpunit --filter ListUsersFeatureTest

And the result should be:

PHPUnit 5.5.4 by Sebastian Bergmann and contributors.

.                                                                   1 / 1 (100%)

Time: 254 ms, Memory: 24.75MB

OK (1 test, 11 assertions)