簡體   English   中英

Rails功能測試:在POST請求中發送URL查詢參數

[英]Rails functional test: sending URL query parameters in POST request

我在Rails功能測試中發送POST請求,如下所示:

post :create, collection: { name: 'New Collection' }

正如預期的那樣, collection作為JSON編碼的表單數據發送。

我無法弄清楚的是如何向URL添加查詢。 文檔說我可以訪問請求對象並在發送之前對其進行修改。 所以我嘗試了這個:

@request.GET[:api_key] = 'my key'
post :create, collection: { name: 'New Collection' }

但是, :api_key永遠不會出現在服務器上的request.GET哈希中。 (但是,當我通過另一個HTTP客戶端發送它時,它會這樣做。)

首先澄清一些事情:雖然請求不能同時是GET和POST,但是在使用POST時沒有什么能阻止你使用查詢字符串和正文表單數據。 您甚至可以使用查詢字符串中的所有參數和空主體進行POST,盡管這聽起來很不尋常。

Rails支持這種情況,實際上您可以使用POST請求輕松發送表單,並且仍然可以在表單的操作中進行查詢。 可以使用request.GET哈希 (這是query_string的別名)訪問查詢,而POST主體使用request.POST哈希request_parameters的別名)進行request_parameters params散列實際上是由組合的GETPOST哈希構造的。

但是,根據我的研究,似乎Rails不支持在功能控制器測試中的POST請求中傳遞查詢字符串 雖然我在github的任何文檔或已知問題中找不到任何相關內容,但源代碼非常清楚。 在下文中,我假設您使用Rails 4。

為什么它不起作用

功能控制器測試的問題在於它們不使用實際請求/響應,但它們模擬HTTP握手:請求被模擬,其參數填充在適當的位置,並且給定的控制器操作被簡單地稱為普通的ruby方法。 所有這些都在action_controller/test_case類中完成

事實證明,由於兩個原因,此模擬在您的特定情況下不起作用:

  1. 運行測試時傳入的參數 交給 無論request_parameters ,即request.POST使用時哈希post請求query_string (即request.GET )用於get測試請求。 在單次測試運行期間,無法設置這兩個哈希值。

    這實際上是有道理的,因為功能測試中的getpost等幫助程序只接受params的單個哈希,因此內部測試代碼無法知道如何將它們分成兩個哈希。

  2. 確實可以在使用@request變量運行測試之前設置請求,但僅在某種程度上,您可以設置標題。 但是您無法設置請求的內部屬性 ,因為它們在測試運行期間被回收 回收在這里完成,它重置請求對象和底層機架請求對象的所有內部變量。 因此,如果您嘗試設置請求GET參數,例如@request.GET[:api_key] = 'my key' ,它將不會產生任何影響,因為表示此哈希的內部變量將在回收期間被擦除。

解決方案/解決方法

  • 放棄功能測試並選擇集成測試 集成測試允許將機架環境變量與主要參數分開設置 以下集成測試除了正常的post body params之外還傳遞QUERY_STRING rack env變量,並且應該完美地工作:

     class CollectionsTest < ActionDispatch::IntegrationTest test 'foo' do post collections_path, { collection: { name: 'New Collection' } }, { "QUERY_STRING" => "api_key=my_api_key" } # this proves that the parameters are recognized separately in the controller # (you can test this in you controller as well as here in the test): puts request.POST.inspect # => {"collection"=>{"name"=>"New Collection"}} puts request.GET.inspect # => {"api_key"=>"my_api_key"} end end 

    您仍然可以在集成測試中使用功能測試的大多數功能。 例如,您可以使用assigns hash測試控制器中已分配的實例變量。

    轉換參數也受到以下事實的支持: Rails 5將棄用功能控制器測試以支持集成測試,並且由於Rails 5.1這些功能測試支持將被移出到單獨的gem。

  • 試試Rails 5:雖然功能測試將被棄用,但它的源代碼似乎已經在rails master中大量重寫 ,例如,不再使用請求的回收。 因此,您可以嘗試嘗試在測試設置期間設置請求的內部變量。 我沒有測試過它。

  • 當然,您總是可以嘗試對功能測試進行修補,以便它支持query_stringrequest_parameters哈希的單獨參數,以便在測試中定義。

我去集成測試路線:)。

我假設控制器名為CollectionsController ,它create動作的路徑是/collections (如果沒有,你只需要調整下面的例子)

而且我還假設您處於請求規范中

這應該工作:

post '/collections?api_key=my_key', collection: { name: 'New Collection' }

post的第二個參數是你將在控制器中收到的所有參數的哈希值。 這樣做:

post :create, collection: { name: 'New Collection' }, more_params: 'stuff', and_so_on: 'things'

這些參數將在控制器中提供:

params[:and_so_on] == 'things'

您想發送POST請求:

我在Rails功能測試中發送POST請求,如下所示:

但是您想要從GET請求中檢索數據:

但是, :api_key永遠不會出現在服務器上的request.GET哈希中。

請求不能同時是GET和POST,如果您要發送POST請求並在查詢字符串中傳遞參數,那么您將在POST請求中獲得這些參數值,GET就沒有任何內容。

然后:

@request.GET[:api_key] = 'my key'
post :create, collection: { name: 'New Collection' }

您正在修改請求中的GET值,但實際上您發送了一個POST請求,這意味着當調用post方法並將請求發送到服務器時,只有您在POST上發送的內容才可用。 只需發送與POST請求捆綁在一起的api密鑰(可能在集合哈希內部)

使用RSpec(v3.4)測試POST操作時,這也是一個問題。

解決方法是模擬request.GETrequest.query_string方法的返回值。

it "should recognise a query parameter in post action" do
  allow(subject.request).to receive(:query_string).and_return("api_key=my%20key")  
  @params = {collection: { name: 'New Collection' }}


  expect(subject.request.query_string).to eq "api_key=my%20key"

  post :create, @params
end

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM