php - 如何执行调用外部 API 的测试控制器 (PHPUnit)
问题描述
我有 2 个文件:MyController.php、APIModel.php
MyController.php
class MyController extends Controller
{
public function post(Request $request)
{
$apiModel = new APIModel;
$apiResponse = $apiModel->GenId();
// Other process such as get data from database, validate data
return view(...);
}
}
APIModel.php
class APIModel extends Model
{
function GenId()
{
$response = $this->callAPI('GET', config('services.api_url.API_URL_GENID'));
}
function callAPI($method, $url, $data = array())
{
$curl = curl_init();
...
try
{
$result = curl_exec($curl);
if (!$result) {
throw new ServiceUnavailableHttpException('Could not connect to interface web service.');
}
}
catch (ServiceUnavailableHttpException $e)
{
throw $e;
}
}
}
现在我想为 MyController@post 执行 phpunit 测试
因为是运行phpunit,所以调用代码行“$apiModel->GenId()”时,出现错误
是否可以创建一个虚拟方法来调用一个虚拟方法而不是调用 $apiModel->GenId()?
我正在使用 Laravel 5.2.45
请帮我!
解决方案
您可以做的是ApiModel
使用服务提供者在容器中注册。
为此,请创建一个新的服务提供者 - 例如调用它ApiServiceProvider
php artisan make:provider ApiServiceProvider
我将假设您只ApiModel
在几个特定的地方使用该实例,因此将推迟它的注册,直到它真正需要它。
use Illuminate\Support\ServiceProvider;
use Illuminate\Contracts\Support\DeferrableProvider;
class ApiServiceProvider extends ServiceProvider implements DeferrableProvider
{
public function register(): void
{
$this->app->singleton(APIModel::class, function () {
return new APIModel;
});
}
public function provides(): array
{
return [APIModel::class];
}
}
现在,通过将实例注入ApiModel
作为第二个参数来更新您的 post 方法
class MyController extends Controller
{
public function post(Request $request, APIModel $client)
{
$apiResponse = $client->GenId();
// Other process such as get data from database, validate data
return view(...);
}
}
接下来,在您的测试中,将绑定替换为ApiModel
$this->mock(APIModel::class, function ($mock) {
$mock->shouldReceive('GenId')->once()->andReturn(1);
});
上面我指定该方法GenId
应该返回1
,但您可以将其更改为您需要的任何内容。
更多关于模拟:模拟对象
ApiModel
或者,您可以简单地使用匿名类并用它替换容器上的实例
$this->instance(APIModel::class, new class {
public function GenId()
{
return 1;
}
});
如果您希望 的其余功能ApiModel
能够完全正常工作并且仅替换GenId
方法,那么您可以扩展它
$this->instance(APIModel::class, new class extends ApiModel {
public function GenId()
{
return 1;
}
});
希望这可以帮助。
推荐阅读
- angular - Web3 和 Angular 11 损坏的依赖项
- iframe - 每 5 分钟重复一次自动刷新 IFrame
- c# - 如何使用访问修饰符声明 sqlConnection、sqlCommand、sqlDataAdapter 和 sqlDataReader?
- swift - Swift 中的正则表达式
- haskell - Haskell quickBatch 测试:Applicative Monoid ZipList
- python - 如何从此板图像中删除阴影
- javascript - 我怎样才能最容易地将此 HTTP 响应解析为 JSON,然后访问 responseText 字段?
- postgresql - 如果所选日期 >= 到 current_date,则使用最小日期更新日期字段,除非所有日期都 >= 到当前日期
- python - Django - 图像未从表单中保存
- arrays - 如何使用 $pull 删除 mongodb 数组中的文档