亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

PHPUnit 給出錯誤:目標 [Illuminate\Contracts\View\] ??

PHPUnit 給出錯誤:目標 [Illuminate\Contracts\View\] ??

PHP
12345678_0001 2023-07-01 17:25:31
我為我的新 Laravel 7 應用程序創建了一個簡單的測試。但是當我運行時php artisan test出現以下錯誤。Target [Illuminate\Contracts\View\Factory] is not instantiable.當我在瀏覽器中轉到該頁面時,不會出現該錯誤。$controller = new HomeController();$request = Request::create('/', 'GET');$response = $controller->home($request);$this->assertEquals(200, $response->getStatusCode());
查看完整描述

3 回答

?
函數式編程

TA貢獻1807條經驗 獲得超9個贊

盡管“只編寫功能測試”可能看起來像是一種逃避(“它們不是單元測試!”),但如果您不想陷入特定于框架的知識的困境,那么這是一個合理的建議。

您會看到,這是使用外觀、全局變量或靜態方法帶來的問題之一。為了使事情正常工作,各種各樣的事情都會在您的代碼(以及您的測試代碼)之外發生。

問題

要了解發生了什么,您首先需要了解 Laravel 如何利用容器和工廠將事物粘合在一起。

接下來,發生的事情是:

  1. 你的代碼(在某個地方HomeController::home()的調用中view()。

  2. view()調用以獲取創建視圖1app()的工廠

  3. app()來電Container::make

  4. Container::make呼叫Container::resolve1

  5. Container::resolve決定需要建造工廠并呼吁Container::build這樣做

  6. 最后Container::build(使用 PHP 的ReflectionClass發現\Illuminate\Contracts\View\Factory無法實例化(因為它是一個接口)并觸發您看到的錯誤。

或者,如果您更像是一個視覺思考者:

http://img4.sycdn.imooc.com/649ff1320001163106540489.jpg

觸發錯誤的原因是框架期望配置容器,以便抽象類(例如接口)已知具體類。

解決方案

現在我們知道發生了什么,并且我們想創建一個單元測試,我們能做什么?

一種解決方案可能似乎使用view.?只需自己注入 View 類即可!但如果您嘗試這樣做,您很快就會發現自己走上了一條基本上在用戶空間中重新創建大量框架代碼的道路。所以這不是一個好主意。

更好的解決方案是模擬view()現在它實際上是一個單元!)。但這仍然需要僅在測試代碼中重新創建框架代碼。還是不太好。[3]

最簡單的事情就是簡單地配置容器并告訴它使用哪個類。此時,您甚至可以模擬 View 類!

現在,純粹主義者可能會抱怨這還不夠“單元”,因為您的測試仍然會在被測代碼之外調用“真實”代碼,但我不同意......

你正在使用框架,所以使用框架!如果您的代碼使用框架提供的粘合,則測試反映此行為是有意義的。只要你不調用非粘合代碼,就沒有問題![4]

最后,為了讓您了解如何做到這一點,舉一個例子!

這個例子

假設您有一個看起來有點像這樣的控制器:

namespace App\Http\Controllers;


class HomeController extends \Illuminate\Routing\Controller

{

? ? public function home()

? ? {

? ? ? ? /* ... */


? ? ? ? return view('my.view');

? ? }

}

那么你的測試[5]可能看起來像這樣:


namespace Tests\Unit\app\Http\Controllers;


use App\Http\Controllers\HomeController;

use Illuminate\Contracts\View\Factory;


class HomeControllerTest extends \PHPUnit\Framework\TestCase

{

? ? public function testHome()

? ? {

? ? ? ? /*/ Arange /*/

? ? ? ? $mockFactory = $this->createMock(Factory::class);


? ? ? ? app()->instance(Factory::class, $mockFactory);


? ? ? ? /*/ Assert /*/

? ? ? ? $mockFactory->expects(self::once())

? ? ? ? ? ? ->method('make')

? ? ? ? ? ? ->with('my.view')

? ? ? ? ;


? ? ? ? /*/ Act /*/

? ? ? ? (new HomeController())->home();

? ? }

}

一個更復雜的示例是還創建一個模擬視圖并由模擬工廠返回它,但我將把它作為練習留給讀者。

腳注

  1. app()要求提供接口Illuminate\Contracts\View\Factory,但沒有傳遞具體的類名

  2. 除了調用另一個函數之外什么也不做的原因Container::make是方法名稱make是由 PSR-11 定義的,并且 Laravel 容器是 PSR 兼容的。

  3. 此外,Laravel 提供的功能測試邏輯已經為您完成了所有這些...

  4. 只是不要忘記用@uses所需的粘合來注釋測試,以避免在 PHPUnit 設置為有關“風險”測試的嚴格模式時發出警告。

  5. 使用“安排、執行、斷言”模式的變體


查看完整回答
反對 回復 2023-07-01
?
收到一只叮咚

TA貢獻1821條經驗 獲得超5個贊

這不是測試端點的方式Laravel。您應該實例化應用程序,因為它已經在項目中設置,

為了使測試正常工作,您應該擴展TestCase.php位于測試文件夾中的 , 。


查看完整回答
反對 回復 2023-07-01
?
搖曳的薔薇

TA貢獻1793條經驗 獲得超6個贊

如果您在《未來》中發現了這一點,并且看到了 @Pothcera 的文字墻,那么您需要了解以下內容:

他這樣做的唯一原因以及您在單元測試中首先看到這一點的唯一原因是因為他和您沒有在測試文件中從 更改PHPUnit\Framework\TestCase為。Tests\TestCase當您擴展包含app().

我的建議是簡單地擴展正確的基礎測試用例并繼續你的生活。


查看完整回答
反對 回復 2023-07-01
  • 3 回答
  • 0 關注
  • 178 瀏覽

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號