久久久久久久av_日韩在线中文_看一级毛片视频_日本精品二区_成人深夜福利视频_武道仙尊动漫在线观看

在 Laravel 測試用例中模擬一個 http 請求并解析路

Simulate a http request and parse route parameters in Laravel testcase(在 Laravel 測試用例中模擬一個 http 請求并解析路由參數)
本文介紹了在 Laravel 測試用例中模擬一個 http 請求并解析路由參數的處理方法,對大家解決問題具有一定的參考價值,需要的朋友們下面隨著小編來一起學習吧!

問題描述

我正在嘗試創建單元測試來測試一些特定的類.我使用 app()->make() 來實例化要測試的類.所以實際上,不需要 HTTP 請求.

I'm trying to create unit tests to test some specific classes. I use app()->make() to instantiate the classes to test. So actually, no HTTP requests are needed.

然而,一些被測試的函數需要來自路由參數的信息,以便他們進行調用,例如request()->route()->parameter('info'),這會拋出異常:

However, some of the tested functions need information from the routing parameters so they'll make calls e.g. request()->route()->parameter('info'), and this throws an exception:

在 null 上調用成員函數 parameter().

Call to a member function parameter() on null.

我玩了很多,嘗試過類似的東西:

I've played around a lot and tried something like:

request()->attributes = new SymfonyComponentHttpFoundationParameterBag(['info' => 5]);  

request()->route(['info' => 5]);  

request()->initialize([], [], ['info' => 5], [], [], [], null);

但他們都沒有工作......

but none of them worked...

我如何手動初始化路由器并向其提供一些路由參數?或者干脆讓 request()->route()->parameter() 可用?

How could I manually initialize the router and feed some routing parameters to it? Or simply make request()->route()->parameter() available?

@Loek:你沒有理解我.基本上,我正在做:

@Loek: You didn't understand me. Basically, I'm doing:

class SomeTest extends TestCase
{
    public function test_info()
    {
        $info = request()->route()->parameter('info');
        $this->assertEquals($info, 'hello_world');
    }
}

沒有請求"涉及.request()->route()->parameter() 調用實際上位于我真實代碼中的一個服務提供者中.此測試用例專門用于測試該服務提供者.沒有一個路由可以打印該提供程序中方法的返回值.

No "requests" involved. The request()->route()->parameter() call is actually located in a service provider in my real code. This test case is specifically used to test that service provider. There isn't a route which will print the returning value from the methods in that provider.

推薦答案

我假設您需要模擬一個請求,而不是實際調度它.模擬請求到位后,您希望探測它的參數值并開發您的測試用例.

I assume you need to simulate a request without actually dispatching it. With a simulated request in place, you want to probe it for parameter values and develop your testcase.

有一種未公開的方法可以做到這一點.你會大吃一驚!

There's an undocumented way to do this. You'll be surprised!

眾所周知,Laravel 的 IlluminateHttpRequest 類基于 SymfonyComponentHttpFoundationRequest.上游類不允許您以 setRequestUri() 方式手動設置請求 URI.它根據實際的請求標頭計算出來.別無他法.

As you already know, Laravel's IlluminateHttpRequest class builds upon SymfonyComponentHttpFoundationRequest. The upstream class does not allow you to setup a request URI manually in a setRequestUri() way. It figures it out based on the actual request headers. No other way around.

好的,閑聊就夠了.讓我們嘗試模擬一個請求:

OK, enough with the chatter. Let's try to simulate a request:

<?php

use IlluminateHttpRequest;

class ExampleTest extends TestCase
{
    public function testBasicExample()
    {
        $request = new Request([], [], ['info' => 5]);

        dd($request->route()->parameter('info'));
    }
}

正如你自己提到的,你會得到一個:

As you mentioned yourself, you'll get a:

錯誤:在 null 上調用成員函數 parameter()

Error: Call to a member function parameter() on null

我們需要一個Route

這是為什么?為什么 route() 返回 null?

看看它的實現 以及它的伴隨方法的實現;getRouteResolver().getRouteResolver() 方法返回一個空閉包,然后 route() 調用它,因此 $route 變量將為 null.然后它被返回,因此......錯誤.

Have a look at its implementation as well as the implementation of its companion method; getRouteResolver(). The getRouteResolver() method returns an empty closure, then route() calls it and so the $route variable will be null. Then it gets returned and thus... the error.

在真實的 HTTP 請求上下文中,Laravel設置它的路由解析器,這樣你就不會得到這樣的錯誤.現在您正在模擬請求,您需要自己進行設置.讓我們看看如何.

In a real HTTP request context, Laravel sets up its route resolver, so you won't get such errors. Now that you're simulating the request, you need to set up that by yourself. Let's see how.

<?php

use IlluminateHttpRequest;
use IlluminateRoutingRoute;

class ExampleTest extends TestCase
{
    public function testBasicExample()
    {
        $request = new Request([], [], ['info' => 5]);

        $request->setRouteResolver(function () use ($request) {
            return (new Route('GET', 'testing/{info}', []))->bind($request);
        });

        dd($request->route()->parameter('info'));
    }
}

查看從 Route 的另一個示例" rel="noreferrer">Laravel 自己的RouteCollection 類.

See another example of creating Routes from Laravel's own RouteCollection class.

所以,現在你不會得到那個錯誤,因為你實際上有一個綁定了請求對象的路由.但它還不會起作用.如果我們此時運行 phpunit,我們會得到一個 null !如果你執行一個 dd($request->route()) 你會看到即使它設置了 info 參數名稱,它的 parameters 數組為空:

So, now you won't get that error because you actually have a route with the request object bound to it. But it won't work yet. If we run phpunit at this point, we'll get a null in the face! If you do a dd($request->route()) you'll see that even though it has the info parameter name set up, its parameters array is empty:

IlluminateRoutingRoute {#250
  #uri: "testing/{info}"
  #methods: array:2 [
    0 => "GET"
    1 => "HEAD"
  ]
  #action: array:1 [
    "uses" => null
  ]
  #controller: null
  #defaults: []
  #wheres: []
  #parameters: [] <===================== HERE
  #parameterNames: array:1 [
    0 => "info"
  ]
  #compiled: SymfonyComponentRoutingCompiledRoute {#252
    -variables: array:1 [
      0 => "info"
    ]
    -tokens: array:2 [
      0 => array:4 [
        0 => "variable"
        1 => "/"
        2 => "[^/]++"
        3 => "info"
      ]
      1 => array:2 [
        0 => "text"
        1 => "/testing"
      ]
    ]
    -staticPrefix: "/testing"
    -regex: "#^/testing/(?P<info>[^/]++)$#s"
    -pathVariables: array:1 [
      0 => "info"
    ]
    -hostVariables: []
    -hostRegex: null
    -hostTokens: []
  }
  #router: null
  #container: null
}

所以通過 ['info' =>5]Request 構造函數沒有任何作用.讓我們看看 Route 類,看看它的 $parameters 屬性 正在填充.

So passing that ['info' => 5] to Request constructor has no effect whatsoever. Let's have a look at the Route class and see how its $parameters property is getting populated.

當我們綁定請求 對路由的對象,$parameters 屬性由對 bindParameters() 方法,該方法依次調用 bindPathParameters() 找出路徑特定的參數(我們沒有本例中的主機參數).

When we bind the request object to the route, the $parameters property gets populated by a subsequent call to the bindParameters() method which in turn calls bindPathParameters() to figure out path-specific parameters (we don't have a host parameter in this case).

該方法將請求的解碼路徑與 Symfony 的 SymfonyComponentRoutingCompiledRoute(您也可以在上面的轉儲中看到該正則表達式)并返回作為路徑參數的匹配項.如果路徑與模式不匹配(這是我們的情況),它將為空.

That method matches request's decoded path against a regex of Symfony's SymfonyComponentRoutingCompiledRoute (You can see that regex in the above dump as well) and returns the matches which are path parameters. It will be empty if the path doesn't match the pattern (which is our case).

/**
 * Get the parameter matches for the path portion of the URI.
 *
 * @param  IlluminateHttpRequest  $request
 * @return array
 */
protected function bindPathParameters(Request $request)
{
    preg_match($this->compiled->getRegex(), '/'.$request->decodedPath(), $matches);
    return $matches;
}

問題在于,當沒有實際請求時,$request->decodedPath() 返回與模式不匹配的 /.所以無論如何參數包都是空的.

The problem is that when there's no actual request, that $request->decodedPath() returns / which does not match the pattern. So the parameters bag will be empty, no matter what.

如果您在 Request 類上遵循 decodedPath() 方法,您將深入了解幾個方法,這些方法最終會從 prepareRequestUri() of SymfonyComponentHttpFoundationRequest.在那里,正是在這種方法中,您將找到問題的答案.

If you follow that decodedPath() method on the Request class, you'll go deep through a couple of methods which will finally return a value from prepareRequestUri() of SymfonyComponentHttpFoundationRequest. There, exactly in that method, you'll find the answer to your question.

它通過探測一堆 HTTP 標頭來確定請求 URI.它首先檢查 X_ORIGINAL_URL,然后是 X_REWRITE_URL,然后是其他一些,最后是 REQUEST_URI 標頭.您可以將這些標頭中的任何一個設置為實際欺騙請求 URI 并實現對 http 請求的最小模擬.讓我們看看.

It's figuring out the request URI by probing a bunch of HTTP headers. It first checks for X_ORIGINAL_URL, then X_REWRITE_URL, then a few others and finally for the REQUEST_URI header. You can set either of these headers to actually spoof the request URI and achieve minimum simulation of a http request. Let's see.

<?php

use IlluminateHttpRequest;
use IlluminateRoutingRoute;

class ExampleTest extends TestCase
{
    public function testBasicExample()
    {
        $request = new Request([], [], [], [], [], ['REQUEST_URI' => 'testing/5']);

        $request->setRouteResolver(function () use ($request) {
            return (new Route('GET', 'testing/{info}', []))->bind($request);
        });

        dd($request->route()->parameter('info'));
    }
}

出乎你的意料,它打印出5info 參數的值.

To your surprise, it prints out 5; the value of info parameter.

您可能希望將功能提取到可在您的測試用例中使用的輔助 simulateRequest() 方法或 SimulatesRequests 特性.

You might want to extract the functionality to a helper simulateRequest() method, or a SimulatesRequests trait which can be used across your test cases.

即使絕對不可能像上述方法那樣欺騙請求 URI,您也可以部分模擬請求類并設置您期望的請求 URI.類似的東西:

Even if it was absolutely impossible to spoof the request URI like the approach above, you could partially mock the request class and set your expected request URI. Something along the lines of:

<?php

use IlluminateHttpRequest;
use IlluminateRoutingRoute;

class ExampleTest extends TestCase
{

    public function testBasicExample()
    {
        $requestMock = Mockery::mock(Request::class)
            ->makePartial()
            ->shouldReceive('path')
            ->once()
            ->andReturn('testing/5');

        app()->instance('request', $requestMock->getMock());

        $request = request();

        $request->setRouteResolver(function () use ($request) {
            return (new Route('GET', 'testing/{info}', []))->bind($request);
        });

        dd($request->route()->parameter('info'));
    }
}

這也會打印出5.

這篇關于在 Laravel 測試用例中模擬一個 http 請求并解析路由參數的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網!

【網站聲明】本站部分內容來源于互聯網,旨在幫助大家更快的解決問題,如果有圖片或者內容侵犯了您的權益,請聯系我們刪除處理,感謝您的支持!

相關文檔推薦

Magento products by categories(按類別劃分的 Magento 產品)
Resource interpreted as image but transferred with MIME type text/html - Magento(資源被解釋為圖像但使用 MIME 類型 text/html 傳輸 - Magento)
Is there an event for customer account registration in Magento?(Magento 中是否有客戶帳戶注冊事件?)
Magento addFieldToFilter: Two fields, match as OR, not AND(Magento addFieldToFilter:兩個字段,匹配為 OR,而不是 AND)
quot;Error 404 Not Foundquot; in Magento Admin Login Page(“未找到錯誤 404在 Magento 管理員登錄頁面)
Get Order Increment Id in Magento(在 Magento 中獲取訂單增量 ID)
主站蜘蛛池模板: 中文字幕在线视频观看 | 成人国产免费观看 | 日本免费视频在线观看 | 天天射视频 | 久久看片| www.青娱乐| 久久久久亚洲 | 久久里面有精品 | 欧美一区二区大片 | 中文字幕电影在线观看 | av网站在线免费观看 | 一区2区 | 亚洲欧美日韩精品久久亚洲区 | 日韩在线观看中文字幕 | 亚洲视频一区二区三区 | 国产一级在线观看 | 国产一二三区在线 | 99久久久国产精品 | 久草在线| 亚洲成人精品在线 | 亚洲一二三区在线观看 | 亚洲a一区二区 | 国产欧美久久精品 | 久久综合伊人 | 欧美日本韩国一区二区 | 久在线视频 | 成人性生交a做片 | 一区二区三区四区在线视频 | 99pao成人国产永久免费视频 | 欧美极品在线视频 | 精品久久久久久中文字幕 | 久久久久久国产精品 | 中文字幕亚洲一区 | 精品久久久久久亚洲综合网 | 欧美精品一二三 | 91精品国产综合久久久久久漫画 | 亚洲成人免费视频在线观看 | 日韩一区二区视频 | 91在线免费观看 | 中文字幕精品视频 | 欧美精品一区二区三区在线 |