Laravel / PHPUnit: как смоделировать param для метода (или для самого конструктора контроллера)? - PullRequest
0 голосов
/ 03 марта 2019

Преамбула: я разрабатываю с Laravel 5.7 и шаблоном Repository / Gateway.

Используя внедрение зависимостей, я могу макетировать и тестировать свои собственные классы, не завися от внешней библиотеки.

Этоэто метод подчеркивания:

/**
     * @param Ip $ip
     * @return string
     * @throws ConnectionError
     * @throws ServiceError
     */
    public function fetchPublicIp(Ip $ip)
    {
        try {
            $public_ip = $ip::get();
            return $public_ip;
        } catch (ConnectionError $e) {
            // If you get here, it means you were unable to reach the ipify service,
            // most likely because of a network error on your end.
            //echo $e->getMessage();
            //return $e;
            throw new ConnectionError();
        } catch (ServiceError $e) {
            // If you get here, it means ipify is having issues, so the request
            // couldn't be completed :(
            throw new ServiceError();
        } catch (\Exception $e) {
            // Something else happened (non-ipify related).
            throw new \Exception();
        }
    }

И в действительности это хорошо протестировано с

/**
     * READ (external)
     * Test that we can get external public IP
     *
     * @return void
     */
    public function test_can_get_public_ip()
    {
        $this->withoutExceptionHandling();

        $mock = Mockery::mock('Ipify\Ip');

        $mock->shouldReceive('get')
            ->andReturn($this->faker->ipv4())
            ->mock();

        $this->assertTrue(class_exists('Ipify\Ip'));
        $this->assertTrue($mock instanceof Ip);
        $gateway = $this->app->make('App\Gateways\PublicIPGateway');
        $public_ip = $gateway->fetchPublicIp($mock);
        $this->assertIsString(filter_var($public_ip, FILTER_VALIDATE_IP));
    }

Теперь, мои сомнения.

Я пишу API, которыйвызывает метод gateway fetchPublicIp.

    PubliIpApiController.php

    /**
     * Update the Public Ip stored in database
     *
     * @return \Illuminate\Http\JsonResponse
     */
    public function update(Ip $ipify)
    {
        $public_ip = $this->getGateway()->fetchPublicIp($ipify);
        // other stuffes here
        return response()->json([
            'public_ip' => $public_ip
        ]);
    }

Но мы в начальной точке.Я могу напрямую протестировать метод update, высмеивая внешний класс Ip.

Но как я могу напрямую протестировать свой собственный вызов API?

Тест заглушки равен

<?php
[...]
$response = $this->get(Route('public_ip_update'));
[...]
?>

Но, разумеется, с этим вызовом я действительно (вновь) связан с внешним IP-адресом.

Итак, как я могу издеваться над внешним классом Ip, чтобы передать макет в качестве параметра дляupdatePublicIp?

Еще одна идея, которую я получил, - перенести зависимость из метода в __construct() контроллера, но проблема та же: как макетировать только конструктор для контроллера?

Псевдокод:

$mock = new Mock('Ipify\Ip');
$public_ip_controller = new PublicIpController($gateway, $mock)
$response = $this->get(Route('public_ip_update'));
...