【发布时间】:2019-11-04 02:45:50
【问题描述】:
是否可以在 Laravel 5.8 中模拟或伪造模型方法的输出?
例如,考虑这个模型
class Website extends Model
{
public function checkDomainConfiguration($domain): bool
{
try {
$records = dns_get_record($domain, DNS_A);
} catch (ErrorException $e) {
return false;
}
if (isset($records[0]['ip']) && $records[0]['ip'] === $this->server->ipv4_address) {
return true;
}
return false;
}
}
为了测试的目的,我需要告诉 phpunit 当这个方法触发时(它在控制器中被调用),如果我故意让它失败,则返回 true 或 false。在测试中我工厂了一个网站,当然它会失败 php 方法dns_get_record。
我已经阅读了 Laravel 文档,并在 google 上搜索了有关模拟模型方法的信息,但似乎找不到任何东西,除了在检查我是否未处于测试模式的方法周围包裹一个大的 if 之外,如果我只是返回 true。
更新 这是我如何在控制器中调用方法的示例
class SomeController extends Controller
{
public function store(Website $website, Domain $domain)
{
if (! $website->checkDomainConfiguration($domain->domain)) {
return response([
'error' => 'error message'
], 500);
}
// continue on here if all good.
}
}
这是测试中的一些代码
$website = factory(Website::class)->create();
$domain = factory(Domain::class)->create([
'website_id' => $website->id
]);
//Mock the website object
$websiteMock = \Mockery::mock(Website::class)->makePartial();
$websiteMock->shouldReceive('getAttribute')
->once()
->with('domain')
->andReturn($website->domain);
$websiteMock->shouldReceive('checkDomainConfiguration')
->with($domain->domain)
->andReturn(true);
app()->instance(Website::class, $websiteMock);
// tried end point like this
$response = $this->json(
'POST',
'api/my-end-point/websites/' . $website->domain . '/domain/' . $domain->id
);
//also tried like this
$response = $this->json(
'POST',
'api/my-end-point/websites/' . $websiteMock->domain . '/domain/' . $domain->id
);
控制器方法接受网站和域模型绑定。如果我在控制器顶部dd(get_class($website)),它会显示实际模型的命名空间,而不是模拟。
【问题讨论】:
-
你能把代码贴在你实际调用该方法的地方吗?你可以这样做,但我需要它来编写更详细的回复。
-
@namelivia 查看我的问题中的更新。谢谢。
标签: php laravel testing mocking phpunit