PHPUnit: действительно ли необходимо использование аннотаций для возврата указанного типа c? - PullRequest
0 голосов
/ 06 апреля 2020

Я пытаюсь ознакомиться с модульным тестированием в PHP с небольшим API в Lumen. Написание первых нескольких тестов было довольно приятно с помощью некоторых учебных пособий, но теперь я столкнулся с моментом, когда мне нужно смоделировать / заглушить зависимость.

Мой контроллер зависит от указанного c пользовательского типа интерфейса, на который намекают Конструктор.
Конечно, я определил этот интерфейс / привязку реализации в ServiceProvider.

    public function __construct(CustomValidatorContract $validator)
    {
        // App\Contracts\CustomValidatorContract
        $this->validator = $validator;
    }

    public function resize(Request $request)
    {
        // Illuminate\Contracts\Validation\Validator
        $validation = $this->validator->validate($request->all());

        if ($validation->fails()) {
            $response = array_merge(
                $validation
                ->errors() // Illuminate\Support\MessageBag
                ->toArray(), 
                ['error' => 'Invalid request data.']
            );

            // response is global helper
            return response()->json($response, 400, ['Content-Type' => 'application/json']);
        }
    }

Как вы можете видеть, мой CustomValidatorContract имеет метод validate(), который возвращает экземпляр Illuminate\Contracts\Validation\Validator (результат проверки). Это в свою очередь возвращает экземпляр Illuminate\Support\MessageBag при вызове errors(). MessageBag тогда имеет toArray() -метод.

Теперь я хочу проверить поведение моего контроллера в случае сбоя проверки.

    /** @test */
    public function failing_validation_returns_400()
    {
        $EmptyErrorMessageBag = $this->createMock(MessageBag::class);
        $EmptyErrorMessageBag
            ->expects($this->any())
            ->method('toArray')
            ->willReturn(array());

        /** @var ValidationResult&\PHPUnit\Framework\MockObject\MockObject $AlwaysFailsTrueValidationResult */
        $AlwaysFailsTrueValidationResult = $this->createStub(ValidationResult::class);
        $AlwaysFailsTrueValidationResult
            ->expects($this->atLeastOnce())
            ->method('fails')
            ->willReturn(true);
        $AlwaysFailsTrueValidationResult
            ->expects($this->atLeastOnce())
            ->method('errors')
            ->willReturn($EmptyErrorMessageBag);

        /** @var Validator&\PHPUnit\Framework\MockObject\MockObject $CustomValidatorAlwaysFailsTrue */
        $CustomValidatorAlwaysFailsTrue = $this->createStub(Validator::class);
        $CustomValidatorAlwaysFailsTrue
            ->expects($this->once())
            ->method('validate')
            ->willReturn($AlwaysFailsTrueValidationResult);

        $controller = new ImageResizeController($CustomValidatorAlwaysFailsTrue);
        $response = $controller->resize(new Request);

        $this->assertEquals(400, $response->status());
        $this->assertEquals(
            'application/json',
            $response->headers->get('Content-Type')
        );
        $this->assertJson($response->getContent());
        $response = json_decode($response->getContent(), true);
        $this->assertArrayHasKey('error', $response);
    }

Несмотря на то, что этот тест работает после дня исследований, я почти уверен, что упустил что-то очень важное здесь. Ни в одном учебнике, который я видел, не упоминалось, что аннотация необходима для того, чтобы убедиться, что тип объекта макета является заданным c. В конце концов это был единственный способ заставить меня работать. Я также обходился без создания настоящих двойных классов и пытался создавать их на лету с помощью встроенных функций. Но я знаю, что возможности есть.

Я был бы очень признателен, если бы вы могли дать мне совет, если он хотя бы близок к ожидаемому методу испытаний.
Нужно ли мне писать аннотацию, если мне приходится иметь дело с Speci c Тип объекта?
Есть ли что-то не так с моей архитектурой, так что это кажется "слишком силен"?

1 Ответ

0 голосов
/ 07 апреля 2020

ОК, я был почти уверен, что PHPUnit выдал ошибку из-за неправильного типа, доставленного в контроллер. На самом деле это было нечто иное.
Эти аннотации необходимы только для удовлетворения Intelephense типа возврата метода getStub() или getMock().
Тест выполняется без ошибок, даже без аннотации.

...