Skip to content

Instantly share code, notes, and snippets.

@tuanpht
Created July 24, 2019 08:35
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save tuanpht/37394e0df10d48d08d0d406c9a7dd477 to your computer and use it in GitHub Desktop.
Save tuanpht/37394e0df10d48d08d0d406c9a7dd477 to your computer and use it in GitHub Desktop.
Laravel Form Request Testing
<?php
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Rules\Unique;
class RegisterRequest extends FormRequest
{
const NAME_MAX_LENGTH = 255;
const EMAIL_MAX_LENGTH = 255;
const PASSWORD_MIN_LENGTH = 8;
/**
* @return array
*/
public function rules()
{
return [
'name' => ['required', 'string', 'max:' . self::NAME_MAX_LENGTH],
'email' => ['required', 'string', 'email', 'max:' . self::EMAIL_MAX_LENGTH, new Unique('users', 'email')],
'password' => ['required', 'string', 'min:' . self::PASSWORD_MIN_LENGTH, 'confirmed'],
];
}
}
<?php
use Tests\TestCase;
use App\Http\Requests\Web\RegisterRequest;
use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\PresenceVerifierInterface;
class RegisterRequestTest extends TestCase
{
public function test_it_contains_valid_rules()
{
$request = new RegisterRequest;
$this->assertEquals([
'name' => ['required', 'string', 'max:' . RegisterRequest::NAME_MAX_LENGTH],
'email' => ['required', 'string', 'email', 'max:' . RegisterRequest::EMAIL_MAX_LENGTH, new Unique('users', 'email')],
'password' => ['required', 'string', 'min:' . RegisterRequest::PASSWORD_MIN_LENGTH, 'confirmed'],
], $request->rules());
}
}
<?php
namespace Tests\Unit\Http\Requests\Web;
use Tests\TestCase;
use App\Http\Requests\Web\RegisterRequest;
use Illuminate\Support\Facades\Validator;
use Mockery;
use Illuminate\Validation\PresenceVerifierInterface;
class RegisterRequestTest extends TestCase
{
/**
* @param array $data Request data
*
* @dataProvider provideDataValidateNameSuccess
*/
public function testValidateNameSuccess($data)
{
$request = new RegisterRequest;
$rules = array_only($request->rules(), 'name');
$validator = Validator::make($data, $rules);
$passed = $validator->passes();
// Can be debug with
// dd($validator->failed());
$this->assertTrue($passed);
}
public function provideDataValidateNameSuccess()
{
return [
[['name' => 'Valid name']],
[['name' => str_repeat('a', RegisterRequest::NAME_MAX_LENGTH)]],
];
}
/**
* @param array $data Request data
*
* @dataProvider provideDataValidateNameFailed
*/
public function testValidateNameFailedWhenMissingInput($data)
{
$request = new RegisterRequest;
$rules = array_only($request->rules(), 'name');
$validator = Validator::make($data, $rules);
$passed = $validator->passes();
$this->assertFalse($passed);
}
public function provideDataValidateNameFailed()
{
return [
[[]],
[['name' => ' ']],
[['name' => '']],
];
}
public function testValidateNameFailedWhenExceedingMaxlength()
{
$request = new RegisterRequest;
$rules = array_only($request->rules(), 'name');
$validator = Validator::make([
'name' => str_repeat('a', RegisterRequest::NAME_MAX_LENGTH + 1),
], $rules);
$passed = $validator->passes();
$this->assertFalse($passed);
}
/**
* Fake database connection when using some db rules, e.g. unique, exists...
*/
private function fakeDatabaseRuleVerifier($validator)
{
$presenceVerifier = Mockery::mock(PresenceVerifierInterface::class);
/*
* Interface PresenceVerifierInterface does not have method setConnection,
* but validator call that method somewhere, so we need to mock that method also.
*
* It's a hack, not good
* https://github.com/laravel/framework/issues/12250
*/
$presenceVerifier->shouldReceive('setConnection');
$validator->setPresenceVerifier($presenceVerifier);
return $presenceVerifier;
}
/**
* @param array $data Request data
*
* @dataProvider provideDataValidateEmailSuccess
*/
public function testValidateEmailSuccess($data)
{
$request = new RegisterRequest;
$rules = array_only($request->rules(), 'email');
$validator = Validator::make($data, $rules);
$presenceVerifier = $this->fakeDatabaseRuleVerifier($validator);
$presenceVerifier->shouldReceive('getCount')->andReturn(0);
$passed = $validator->passes();
$this->assertTrue($passed);
}
public function provideDataValidateEmailSuccess()
{
return [
[['email' => 'validemail@example.com']],
];
}
/**
* @param array $data Request data
*
* @dataProvider provideDataValidateEmailFailedWhenEmailInvalid
*/
public function testValidateEmailFailedWhenEmailInvalid($data)
{
$request = new RegisterRequest;
$rules = array_only($request->rules(), 'email');
$validator = Validator::make($data, $rules);
$presenceVerifier = $this->fakeDatabaseRuleVerifier($validator);
// We are testing email format
// so we make getCount return 0, meaning email had not existed in db
$presenceVerifier->shouldReceive('getCount')->andReturn(0);
$passed = $validator->passes();
$this->assertFalse($passed);
}
public function provideDataValidateEmailFailedWhenEmailInvalid()
{
return [
[[]],
[['email' => '']],
[['email' => ' ']],
[['email' => 'missingdomain']],
[['email' => '@missinguser.com']],
[['email' => 'invalidchar &*@example.com']],
[['email' => 'exceedlength' . str_repeat('a', RegisterRequest::EMAIL_MAX_LENGTH + 1) . '@example.com']],
];
}
public function testValidateEmailFailedWhenEmailExisted()
{
$request = new RegisterRequest;
$rules = array_only($request->rules(), 'email');
$validator = Validator::make([
'email' => 'existedemail@example.com',
], $rules);
$presenceVerifier = $this->fakeDatabaseRuleVerifier($validator);
$presenceVerifier->shouldReceive('getCount')->andReturn(1);
$passed = $validator->passes();
$this->assertFalse($passed);
}
/**
* @param array $data Request data
*
* @dataProvider provideDataValidatePasswordFailedWhenInputInvalid
*/
public function testValidatePasswordFailedWhenInputInvalid($data)
{
$request = new RegisterRequest;
$rules = array_only($request->rules(), 'password');
$validator = Validator::make($data, $rules);
$passed = $validator->passes();
$this->assertFalse($passed);
}
public function provideDataValidatePasswordFailedWhenInputInvalid()
{
return [
[[]],
[['password' => '']],
[['password' => ' ']],
[['password' => str_repeat('a', RegisterRequest::PASSWORD_MIN_LENGTH - 1)]],
];
}
/**
* @param array $data Request data
*
* @dataProvider provideDataValidatePasswordSuccess
*/
public function testValidatePasswordSuccess($data)
{
$request = new RegisterRequest;
$rules = array_only($request->rules(), 'password');
$validator = Validator::make($data, $rules);
$passed = $validator->passes();
$this->assertTrue($passed);
}
public function provideDataValidatePasswordSuccess()
{
return [
[['password' => ' 12345678 ', 'password_confirmation' => ' 12345678 ']],
[
[
'password' => str_repeat('a', RegisterRequest::PASSWORD_MIN_LENGTH),
'password_confirmation' => str_repeat('a', RegisterRequest::PASSWORD_MIN_LENGTH),
],
],
[
[
'password' => str_repeat('a', RegisterRequest::PASSWORD_MIN_LENGTH + 1),
'password_confirmation' => str_repeat('a', RegisterRequest::PASSWORD_MIN_LENGTH + 1),
],
],
];
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment