[英]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
散列實際上是由組合的GET
和POST
哈希構造的。
但是,根據我的研究,似乎Rails不支持在功能控制器測試中的POST請求中傳遞查詢字符串 。 雖然我在github的任何文檔或已知問題中找不到任何相關內容,但源代碼非常清楚。 在下文中,我假設您使用Rails 4。
功能控制器測試的問題在於它們不使用實際請求/響應,但它們模擬HTTP握手:請求被模擬,其參數填充在適當的位置,並且給定的控制器操作被簡單地稱為普通的ruby方法。 所有這些都在action_controller/test_case
類中完成 。
事實證明,由於兩個原因,此模擬在您的特定情況下不起作用:
運行測試時傳入的參數都 交給 無論對request_parameters
,即request.POST
使用時哈希post
請求或到query_string
(即request.GET
)用於get
測試請求。 在單次測試運行期間,無法設置這兩個哈希值。
這實際上是有道理的,因為功能測試中的get
, post
等幫助程序只接受params的單個哈希,因此內部測試代碼無法知道如何將它們分成兩個哈希。
確實可以在使用@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_string
和request_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.GET
或request.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.