我正在使用GeocoderLaravel在Laravel应用程序中通过Google Maps API处理查找位置。我希望能够模拟外观,以便在测试中它实际上不会查询 Google Maps API,所以我将其注入控制器,但这样做会破坏控制器。以下是控制器的相关部分:
<?php
namespace App'Http'Controllers;
use Illuminate'Http'Request;
use App'Http'Requests;
use App'Http'Controllers'Controller;
use App'Location;
use Geocoder;
class LocationController extends Controller
{
protected $geocoder;
public function __construct(Geocoder $geocoder)
{
$this->geocoder = $geocoder;
}
/**
* Store a newly created resource in storage.
*
* @param 'Illuminate'Http'Request $request
* @return 'Illuminate'Http'Response
*/
public function store(Request $request)
{
// Get location
$location = $request->input('location');
try {
// Look up location
$result = $this->geocoder->geocode($location);
// Return response
return response()->json($result->toArray(), 200);
} catch ('Exception $e) {
$data = [
'message' => $e->getMessage()
];
return response()->json($data, 400);
}
}
}
当我运行测试或尝试向此方法发出请求时,我收到以下错误:
PHP Fatal error: Call to undefined method Toin0u'Geocoder'Facade'Geocoder::geocode()
使用 PsySh 在调用断点之前插入断点,看起来确实定义了 geocode()
方法,但我不确定为什么。谁能解释我哪里出错了?
你不能
像那样注入门面。立面没有geocode
方法。
外墙很特别,因为它们只提供对Laravel IoC的访问,并且不像普通课程那样表现。它们与依赖注入正交。
如果服务提供商创建了别名,则可以注入真正的Geocoder'Geocoder
类,但它似乎不是这样设置的。
我认为你像往常一样使用门面,就像Geocoder::geocode(...)
一样.
然而。。。查看Laravel如何在测试期间模拟外观:
https://laravel.com/docs/5.1/testing#mocking-facades
这将允许你测试你的控制器,模拟外观调用,这样它就不会真正击中谷歌。
更新:
我创建了一个拉取请求以使此 DI 友好:
https://github.com/geocoder-php/GeocoderLaravel/pull/41
如果该请求被合并,您将能够在您的控制器方法中注入'Geocoder'Geocoder
,我自己非常喜欢!