Как провести модульный тест prepareForValidation в запросе формы laravel?

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

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

Ниже приведен мой класс Request (правила и методы 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 to route не меняет пароль, даже если он передан в наборе данных.

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

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

1 ответ

Решение

Это могло быть что-то вроде этого (я не издевался над 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);
    }
}
Другие вопросы по тегам