IT이야기

Rails 기능 테스트에서 원시 포스트 데이터를 보내는 방법

cyworld 2021. 4. 21. 21:24
반응형

Rails 기능 테스트에서 원시 포스트 데이터를 보내는 방법은 무엇입니까?


테스트를 위해 내 컨트롤러 중 하나에 원시 게시물 데이터 (예 : 매개 변수화되지 않은 JSON)를 보내려고합니다.

class LegacyOrderUpdateControllerTest < ActionController::TestCase
  test "sending json" do
    post :index, '{"foo":"bar", "bool":true}'
  end
end

그러나 이것은 나에게 NoMethodError: undefined method `symbolize_keys' for #<String:0x00000102cb6080>오류를 준다 .

원시 게시물 데이터를 보내는 올바른 방법은 무엇입니까 ActionController::TestCase?

다음은 컨트롤러 코드입니다.

def index
  post_data = request.body.read
  req = JSON.parse(post_data)
end

나는 오늘 같은 문제를 겪었고 해결책을 찾았습니다.

당신에하는 것은 test_helper.rb다음과 같은 방법의 내부를 정의한다 ActiveSupport::TestCase:

def raw_post(action, params, body)
  @request.env['RAW_POST_DATA'] = body
  response = post(action, params)
  @request.env.delete('RAW_POST_DATA')
  response
end

기능 테스트에서 post메서드 처럼 사용 하되 원시 게시물 본문을 세 번째 인수로 전달하십시오.

class LegacyOrderUpdateControllerTest < ActionController::TestCase
  test "sending json" do
    raw_post :index, {}, {:foo => "bar", :bool => true}.to_json
  end
end

나는 이것을 사용하여 원시 포스트 본문을 읽을 때 Rails 2.3.4에서 테스트했습니다.

request.raw_post

대신에

request.body.read

소스 코드 를 살펴보면 env 해시 에서 이를 확인하여 raw_post래핑 request.body.read하는 것을 볼 수 있습니다 .RAW_POST_DATArequest


실제로 rspec 게시 요청을 시뮬레이션하기 전에 한 줄만 추가하면 동일한 문제를 해결했습니다. 당신이하는 일은 "RAW_POST_DATA"를 채우는 것입니다. 나는 post : create에서 var 속성을 제거하려고 시도했지만 그렇게하면 작업을 찾지 못했습니다.

여기 내 해결책.

def do_create (속성)
  request.env [ 'RAW_POST_DATA'] = attributes.to_json
  포스트 : 생성, 속성
종료 

컨트롤러에서 JSON을 읽는 데 필요한 코드는 다음과 유사합니다.

  @property = Property.new (JSON.parse (request.body.read))

테스트를 실행하는 스택 추적을 보면 요청 준비시 더 많은 제어를 얻을 수 있습니다. ActionDispatch :: Integration :: RequestHelpers.post => ActionDispatch :: Integration :: Session.process => Rack :: Test :: Session.env_for

json 문자열을 : params로 전달하고 콘텐츠 유형 "application / json"을 지정할 수 있습니다. 다른 경우에는 콘텐츠 유형이 "application / x-www-form-urlencoded"로 설정되고 json이 제대로 구문 분석됩니다.

따라서 "CONTENT_TYPE"을 지정하기 만하면됩니다.

post :index, '{"foo":"bar", "bool":true}', "CONTENT_TYPE" => 'application/json'

Rails5 + 통합 테스트를 사용하는 경우 (문서화되지 않은) 방법은 params 인수에 문자열을 전달하는 것입니다.

post '/path', params: raw_body, headers: { 'Content-Type' => 'application/json' }

RSpec (> = 2.12.0)을 사용하고 요청 사양을 작성하는 경우 포함 된 모듈은 ActionDispatch::Integration::Runner. 소스 코드를 살펴보면 post 메소드가 매개 변수 를 받아들이는 프로세스호출 한다는 것을 알 수 있습니다 rack_env.

이 모든 것은 사양에서 다음을 수행 할 수 있음을 의미합니다.

#spec/requests/articles_spec.rb

post '/articles', {}, {'RAW_POST_DATA' => 'something'}

그리고 컨트롤러에서 :

#app/controllers/articles_controller.rb

def create
  puts request.body.read
end

Rails 5 용 버전 :

post :create, body: '{"foo": "bar", "bool": true}'

여기를 참조 하십시오 - body문자열 매개 변수는 원시 요청 본문으로 처리됩니다.


Rails 4를 사용하여 컨트롤러에 게시되는 원시 xml의 처리를 테스트하기 위해이 작업을 수행하려고했습니다. 게시물에 문자열을 제공하기 만하면됩니다.

raw_xml = File.read("my_raw.xml")
post :message, raw_xml, format: :xml

제공된 매개 변수가 문자열이면 컨트롤러에 본문으로 전달됩니다.


post메서드는 이름-값 쌍의 해시를 예상하므로 다음과 같은 작업을 수행해야합니다.

post :index, :data => '{"foo":"bar", "bool":true}'

그런 다음 컨트롤러에서 다음과 같이 구문 분석 할 데이터를 가져옵니다.

post_data = params[:data]

Rails 4.1.5부터는 이것이 저에게 효과적이었습니다.

class LegacyOrderUpdateControllerTest < ActionController::TestCase
  def setup
    @request.headers["Content-Type"] = 'application/json'
  end

  test "sending json" do
    post :index, '{"foo":"bar", "bool":true}'.to_json, { account_id: 5, order_id: 10 }
  end
end

/ accounts / 5 / orders / 10 / items의 URL에 대해 이것은 전달 된 URL 매개 변수와 JSON 본문을 가져옵니다. 물론 주문이 포함되지 않은 경우 params 해시를 생략 할 수 있습니다.

class LegacyOrderUpdateControllerTest < ActionController::TestCase
  def setup
    @request.headers["Content-Type"] = 'application/json'
  end

  test "sending json" do
    post :index, '{"foo":"bar", "bool":true}'.to_json
  end
end

레일즈 5.1에서는 본문에 데이터가 필요한 삭제 요청을 수행 할 때 다음 작업이 수행됩니다.

delete your_app_url, as: :json, env: {
   "RAW_POST_DATA" =>  {"a_key" => "a_value"}.to_json
}

참고 : 이것은 통합 테스트를 수행 할 때만 작동합니다.


통합 테스트 (Rails 5.1)에서 원시 JSON 콘텐츠를 게시하는 방법을 오랫동안 찾고있었습니다. 이 경우 내 솔루션이 도움이 될 수 있다고 생각합니다. post메서드에 대한 문서와 소스 코드를 찾았습니다 . https://api.rubyonrails.org/v5.1/classes/ActionDispatch/Integration/RequestHelpers.html#method-i-post

이것은 저를 지시 process자세한 내용은 방법 : https://api.rubyonrails.org/v5.1/classes/ActionDispatch/Integration/Session.html#method-i-process

Thanks to this, I finally found out what parameters are accepted by the process and thus post method. Here's what my final solution looked like:

post my_url, params: nil, headers: nil, env: {'RAW_POST_DATA' => my_body_content}, as: :json

post :index, {:foo=> 'bar', :bool => 'true'}

ReferenceURL : https://stackoverflow.com/questions/2103977/how-to-send-raw-post-data-in-a-rails-functional-test

반응형