Testing Laravel - 測試 Middleware - 取用 url 路徑上的變數
Testing Laravel - 測試 Middleware - 取用 url 路徑上的變數
本文章使用的開發環境為
PHP : 8.0.8
Laravel : 8.51.0
這週在開發上遇到了一個情境,我想要對某一個 Route 的多個 Middleware 中的其中一個 Middleware 去寫測試
帶有多個 Middleware 的 Route
1 | Route::get('lets_test_middleware/{message}', function () {}) |
而我在 WaitForTestMiddleware
中則會取用到 lets_test_middleware/{message}
路徑上的 message
參數,假設我們會把他放到 Session
中好了
WaitForTestMiddleware
1 | class WaitForTestMiddleware |
一開始我寫的測試像是這樣
WaitForTestMiddlewareTest
1 | class WaitForTestMiddlewareTest extends TestCase |
在執行測試的時候卻遇到一個錯誤
1 | Error : Call to a member function parameter() on null |
這讓人滿納悶的,明明我是依照 Request
提供的 Api 去生成 $request
,為什麼會在 $request->route()
得到 null
的結果呢?
經過一段時間的搜尋跟深入底層的 code 去釐清,最後參照這篇文章 Simulate a http request and parse route parameters in Laravel testcase ,終於大概理解原由了
其原因在於,當我們呼叫 $request->route()
的時候
src/Illuminate/Http/Request.php#L530
1 | public function route($param = null, $default = null) |
由上我們可以看到在第 3 行處,我們會先去呼叫 getRouteResolver()
所以這邊我們繼續往下追,看一下 getRouteResolver()
src/Illuminate/Http/Request.php#L601
1 | public function getRouteResolver() |
由此可知, $this->routeResolver
是未設定過的,這是因為當在 Laravel 接真實的 HTTP Request 的時候,在生成 Request 的生命週期中會去設定 routeResolver
,但我們在測試中手動去生成的時候卻沒有經過設定的環節
所以,其實我們只要補上 routeResolver
的設定就可以了,也正好 Request 物件有提供我們一個 setRouteResolver()
方法可以使用,底下我將測試改寫為有設置 routeResolver
的版本
WaitForTestMiddlewareTest
1 | class WaitForTestMiddlewareTest extends TestCase |
設定完之後我們就可以如期的驗證了