gpt4 book ai didi

php - 可以在 Laravel/PHPUnit 中模拟模型方法输出吗?

转载 作者:行者123 更新时间:2023-11-28 20:13:06 26 4
gpt4 key购买 nike

是否可以在 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 当此方法触发时(它在 Controller 中调用)返回 true,如果我故意希望它失败则返回 false。在测试中我建立了一个网站,当然它会失败 php 方法 dns_get_record

我已经阅读了 Laravel 文档,并搜索了关于模拟模型方法的谷歌,但似乎找不到任何东西,除了在检查我是否不在测试模式下,如果我只是返回 true。 <-- 呸。

更新这是我如何在 Controller 中调用方法的示例

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
);

Controller 方法接受网站和域模型绑定(bind)。如果我在 Controller 的顶部 dd(get_class($website)),它会显示实际模型的 namespace ,而不是模拟。

最佳答案

在您的代码中,您将模型作为参数注入(inject) Controller ,这意味着 Laravel 的 ioc 将被要求提供 Website 模型的实例,并将在执行实际代码时提供它。

在您的测试中,您可以创建一个模拟,然后告诉 ioc 在请求 Website 实例时返回该模拟,例如:

$websiteMock = Mockery::mock(Website::class);
app()->instance(Website::class, $websitemock)

在执行你的 Controller 之前。现在,当在您的测试中执行 Controller 时,模拟将是接收方法调用的那个,您可以将其设置为期望它们并伪造响应。特别是在您的代码上,您的模拟应该期望并伪造两个调用,例如:

$websiteMock->shouldReceive('getAttribute')
->once()
->with('domain')
->andReturn('test.domain'):
$websiteMock->shouldReceive('checkDomainConfiguration')
->once()
->with('test.domain')
->andReturn(false):

编辑整个代码(我已经编造了一些不重要的东西,比如路由或 Controller 名称,使用你自己的)。

Controller

<?php

namespace App\Http\Controllers;

use App\Domain;
use App\Website;

class StackOverflowController extends Controller
{
public function store(Website $website, Domain $domain)
{
if (! $website->checkDomainConfiguration($domain->domain)) {
return response([
'error' => 'error message'
], 500);
}
}
}

集成测试

public function testStackOverflow()
{
$website = Mockery::mock(Website::class);
app()->instance(Website::class, $website);
$domain = Mockery::mock(Domain::class);
app()->instance(Domain::class, $domain);

$domain->shouldReceive('getAttribute')
->once()
->with('domain')
->andReturn('some.domain');

$website->shouldReceive('checkDomainConfiguration')
->once()
->with('some.domain')
->andReturn(false);
$response = $this->json('POST', '/stack/websiteId/overflow/domainId');
$this->assertEquals('error message', json_decode($response->getContent())->error);
$this->assertEquals(500, $response->status());
}

我也没有包含集成测试文件的开头,但仔细检查你是否包含:

use App\Domain;
use App\Website;

关于php - 可以在 Laravel/PHPUnit 中模拟模型方法输出吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56700224/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com