2017-10-09 92 views
0

我仍在學習有關Laravel和依賴注入的過程。我理解這個概念,但我不知道如何嘲笑在這種特殊情況下的依賴關係:通過嘲笑依賴關係測試Laravel自定義包

MyController.php

use Illuminate\Routing\Controller;  
use MyPackage\Services\ServiceInterface; 

class MyController extends Controller{ 
    protected $service; 

    public function __construct(ServiceInterface $service) 
    { 
     $this->service = $service; 
    }  
} 

MyServiceProvider.php

use Illuminate\Support\ServiceProvider; 

class MyServiceProvider extends ServiceProvider{ 

    public function register() 
    { 
     $this->app->bind('MyPackage\Services\ServiceInterface', function ($app) { 
      return new MyPackage\Services\ConcreteService(['key'=>'123'], $app->make('GuzzleHttp\Client')); 
     }); 
    }  
} 

所以,如你所見,我有一個需要ServiceInterface實例的控制器。該實例正在ServiceProvider中解析。 ConcreteService的構造函數需要客戶端對API執行Http請求。這個Http正在被Service容器解析(這將是一個Guzzle的實例)。

現在,我該如何在我的測試中嘲笑這個Guzzle的實例?

理想的結果做這樣的事情:

MyTest.php

... 
$this->post(route('routeToActionInMyController'), $params); 

所以,在我的測試中,我只需要點擊將要使用的myController的一個具體方法途徑.php但我不需要一個「真正的」Guzzle實例。我只需要模擬響應來測試MyController是否以預期的方式運行(並將事情正確地存儲在數據庫中)。

如何指示服務容器在測試期間注入模擬對象?還是我以完全錯誤的方式做這件事?

任何幫助將不勝感激。

在此先感謝

+0

'類MyServiceProvider extends Controller'看起來非常糟糕的做法。控制器和服務提供商的目的是爲完全不同的事情負責 – apokryfos

+0

哦,我很抱歉,這是一個錯字 –

回答

0

在您的測試類:

class TestingSomething extends TestCase { 
    protected function setUp() { 
      parent::setUp(); 
      $mockServiceInterface = $this->getMockBuilder(ServiceInterface::class)->getMock(); 
      $this->app->instance(ServiceInterface::class,$mockServiceInterface); 
    } 

    public function testPostToRoute() { 
     $this->post(route('routeToActionInMyController'), $params); 
    } 
} 

這應該更換什麼在與模擬實例的服務容器已經綁定。

請參閱PHPUnit manual on chapter 9. Test doubles瞭解模擬生成器和生成的模擬可以執行的操作。

+0

感謝您的回覆@apokryfos。這意味着我需要替換整個綁定?我的意思是,我不能只取代Guzzle綁定? –

+0

如果你通過依賴注入來實例化guzzle,那麼你可以模擬guzzle客戶端。這也應該工作 – apokryfos

+0

我覺得Guzzle有這個開箱即用。檢查http://docs.guzzlephp.org/en/stable/testing.html – apokryfos