Как разместить данные JSON в функциональном тесте rails 3 - PullRequest
15 голосов
/ 30 апреля 2011

Я планирую использовать данные JSON как в запросе, так и в ответе в моем проекте, и у меня возникли некоторые проблемы при тестировании.

После поиска я нахожу следующий код, который использует curl для публикации данных JSON:

curl -H "Content-Type:application/json" -H "Accept:application/json" \
    -d '{ "foo" : "bar" }' localhost:3000/api/new

В контроллере я могу получить доступ к данным JSON, просто используя params[:foo], что действительно просто.Но для функционального тестирования я нахожу только post и xhr (псевдоним для xml_http_request).

Как написать функциональный тест в рельсах для достижения того же эффекта, что и при использовании curl?Или я должен сделать тест другими способами?

Вот что я попробовал.Я нашел реализацию xhr в action_controller/test_case.rb и попытался добавить метод jhr, просто изменив «Conetent-Type» и «HTTP_ACCEPT».(Добавлено в test/test_helpers.rb.)

def json_http_request(request_method, action, parameters = nil, session = nil, flash = nil)
  @request.env['Content-Type'] = 'Application/json'
  @request.env['HTTP_ACCEPT'] ||= [Mime::JSON, Mime::JS, Mime::HTML, Mime::XML, 'text/xml', Mime::ALL].join(', ')
  __send__(request_method, action, parameters, session, flash).tap do
    @request.env.delete 'Content-Type'
    @request.env.delete 'HTTP_ACCEPT'
  end
end
alias jhr :json_http_request

Я использовал это так же, как xhr, но это не работает.Я осмотрел объект @response и обнаружил, что тело " ".

Я также нахожу один похожий вопрос о переполнении стека, но он предназначен для рельсов 2, а ответ для публикации необработанных данныхне работает в рельсах 3.

Ответы [ 7 ]

16 голосов
/ 01 сентября 2016

Начиная с Rails 5, способ сделать это:

post new_widget_url, as: :json, params: { foo: "bar" }

Это также правильно установит заголовок Content-type (application/json).

10 голосов
/ 01 марта 2013

Я обнаружил, что это именно то, что я хочу - отправить JSON в действие контроллера.

post :create, {:format => 'json', :user => { :email => "test@test.com", :password => "foobar"}}
9 голосов
/ 28 октября 2011

Просто укажите соответствующий тип контента:

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

Данные Json должны идти как строка, а не как хеш. Глядя на трассировку стека при выполнении теста, вы можете получить больше контроля при подготовке запроса: ActionDispatch :: Integration :: RequestHelpers.post => ActionDispatch :: Integration :: Session.process => Rack :: Test :: Session.env_for

Указание: формат не работает, потому что запрос идет как application / x-www-form-urlencoded, а json не обрабатывается должным образом при обработке тела запроса.

3 голосов
/ 14 марта 2013

Предположим, у вас есть контроллер с именем api, метод с именем new и вы тестируете контроллер api:

@request.env["RAW_POST_DATA"] = '{ "foo" : "bar" }'
post :new

помог мне.

1 голос
/ 17 апреля 2013

Вот фрагмент, который позволяет мне публиковать данные json для тестирования моего собственного приложения.рельсы 3

port = Rails.env.production? ? 80 : 3000
uri = URI.parse( Rails.application.routes.url_helpers.books_url(:host => request.host, :port => port, :format => :json) )
http = Net::HTTP.new(uri.host, uri.port)
request = Net::HTTP::Post.new(uri.request_uri)
request.content_type = 'application/json'
request.body = @json_data
response = http.request( request )
@result = response.body

Надеюсь, что это помогает другим

0 голосов
/ 04 февраля 2015

Лучший ответ, который я могу придумать, это Вы не

Было ли это намеренно, возможно, хорошо, что rails не реализует это для вас.

В функциональных тестах вы действительно хотите просто протестировать свой контроллер и не метод рельсов десериализации или даже то, что маршрутизация и обнаружение пантомимы настроены правильно, все они попадают под IntegrationTest.

Так что для ваших контроллеров, не передавайте JSON, просто передавайте ваш хэш params, как вы это обычно делаете.Возможно добавление: format в качестве аргумента, если вам нужно проверить это и ответить по-другому.

Если вы хотите проверить полный стек, перейдите к IntegrationTest

0 голосов
/ 26 января 2013

Как @taro предлагает в комментарии выше, синтаксис, который работает для меня в функциональных и интеграционных тестах:

post :create, {param1: 'value1', param2: 'value2', format: 'json'}

(фигурные скобки не всегда необходимы, но иногда это не такработать, если они отсутствуют, поэтому я всегда добавляю их.)

Вот как выглядит params и request.format для такого сообщения:

params: {"param1" =>"значение1", "парам2" => "значение2", "формат" => "json", "контроллер" => "вещи", "действие" => "создать"}

request.format:применение / JSON

...