#laravel #mocking #phpunit
#laravel #издевательство #phpunit
Вопрос:
Преамбула: я разрабатываю с использованием Laravel 5.7 и шаблона репозитория / шлюза.
Используя внедрение зависимостей, я могу издеваться и тестировать свои собственные классы, на самом деле не завися от внешней библиотеки.
Это метод подчеркивания:
/**
* @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('IpifyIp');
$mock->shouldReceive('get')
->andReturn($this->faker->ipv4())
->mock();
$this->assertTrue(class_exists('IpifyIp'));
$this->assertTrue($mock instanceof Ip);
$gateway = $this->app->make('AppGatewaysPublicIPGateway');
$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 IlluminateHttpJsonResponse
*/
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('IpifyIp');
$public_ip_controller = new PublicIpController($gateway, $mock)
$response = $this->get(Route('public_ip_update'));