嘲笑地理编码器拉拉维尔


Mocking GeocoderLaravel

我正在使用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,我自己非常喜欢!