Background: In my Laravel project, I am implementing the user creation function where an admin can create users. During user creation I'm setting a random password (not an input) and sending a password reset email to user. On my schema password field is not nullable (I don't want any users without passwords in the database).
I'm using Form Request to implement the controller validation and prepareForValidation to set the random password on POST but sets the password to null on PATCH as I don't want the password to be updated on user update event. (Admins can update user profiles but not the passwords.) And validation rules 'sometimes' handles the two scenarios.
Below is from my Request class (rules and prepareForValidation methods).
class AdminUserRequest extends FormRequest
{
public function rules()
{
return [
...
'password' => [
'sometimes',
'required',
'min:8',
],
...
];
}
/**
* Prepare the data for validation.
*
* @return void
*/
protected function prepareForValidation()
{
if ($this->getMethod() == 'POST') {
$this->merge([
'password' => Hash::make(Str::random(10)),
]);
} else {
$this->offsetUnset('password');
}
}
}
Question: My question is what's the best way to unit test functionality of prepareForValidation in Form Request.
It should test that the request data set has a password on POST and and not set on other methods.
Of course I can do functional testing to cover the cases
But I'd like to know if there's a way to unit test this. And how to do it.
Thanks in advance
It could be something like this (I didn't mock the request
and arrange expectations on it - instead kept it simple). The last method is for private/protected
method invocation of the classes. This can be moved to TestCase
class for future usages.
class AdminUserRequestTest extends TestCase
{
/**
* @test
* @covers ::prepareForValidation
*/
function it_should_add_password_when_it_is_post_method()
{
$request = new AdminUserRequest();
$request->setMethod('POST');
$hashedPassword = 'a1b2c3d4e5';
Hash::shouldReceive('make')->andReturn($hashedPassword);
$this->invokeMethod($request, 'prepareForValidation');
$this->assertSame($request->get('password'), $hashedPassword);
}
/**
* @test
* @covers ::prepareForValidation
*/
function it_should_unset_password_when_it_is_not_post_method()
{
$request = new AdminUserRequest();
$request->setMethod('PUT'); // it could be something else besides POST
$this->invokeMethod($request, 'prepareForValidation');
$this->assertFalse($request->has('password'));
}
protected function invokeMethod(&$object, $methodName, array $parameters = [])
{
$reflection = new ReflectionClass(get_class($object));
$method = $reflection->getMethod($methodName);
$method->setAccessible(true);
return $method->invokeArgs($object, $parameters);
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With