Как выполнить модульный тест prepareForValidation в запросе формы laravel? - PullRequest
1 голос
/ 17 июня 2020

Фон: В моем проекте Laravel я реализую функцию создания пользователей, в которой администратор может создавать пользователей. Во время создания пользователя я устанавливаю случайный пароль (не ввод) и отправляю пользователю электронное письмо для сброса пароля. В моей схеме поле пароля не допускает значения NULL (мне не нужны пользователи без паролей в базе данных).

Я использую Form Request для реализации проверки контроллера и prepareForValidation для установки случайного пароля на POST , но устанавливаю пароль на ноль на PATCH , как я не Я хочу, чтобы пароль обновлялся при обновлении пользователя. (Администраторы могут обновлять профили пользователей, но не пароли.) И правила проверки «иногда» обрабатывают два сценария ios.

Ниже приведен мой класс запроса ( правила и prepareForValidation методы).

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');
        }
    }
}

Вопрос: Мой вопрос: как лучше всего проверить функциональность prepareForValidation в форме запроса.

Он должен проверить, что набор данных запроса имеет пароль при POST и не установлен для других методов.

Конечно, я могу провести функциональное тестирование, чтобы охватить случаи

  • POST для маршрута создает пользователя в базе данных и не имеет ошибок в сеансе
  • PATCH для маршрута не меняет пароль, даже если он передан в наборе данных.

Но Я хотел бы знать, есть ли способ провести модульное тестирование. И как это сделать.

Заранее спасибо

1 Ответ

2 голосов
/ 17 июня 2020

Это могло быть что-то вроде этого (я не издевался над request и не ограничивал его ожидания - вместо этого я оставил его простым). Последний метод предназначен для вызова private/protected методов классов. Его можно переместить в класс TestCase для использования в будущем.

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);
    }
}
...