Laravel / PHPUnit:如何模拟方法(或构造函数控制器本身)的参数?

时间:2019-03-03 10:14:36

标签: laravel mocking phpunit

序言:我正在使用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));
    }

现在,我的疑问。

我正在编写一个调用gateway方法fetchPublicIp的API。

    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

我得到的另一个想法是将依赖关系从方法移至Controller的__construct(),但是问题是相同的:如何仅模拟控制器的构造函数?

伪代码:

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

0 个答案:

没有答案