-
-
Notifications
You must be signed in to change notification settings - Fork 68
Testing Features and Jobs
Every generated Feature and/or Job will get a test class generated with it, acting as the unit test of the corresponding Feature/Job.
- 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.
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();
}
}
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.
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.
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');
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));
}
}
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.
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)