RSpec没有以JSON格式发送Post请求

时间:2016-02-17 17:56:03

标签: ruby-on-rails ruby json rspec

我正在做一个Rails应用程序,它主要是一个API。我正在尝试为我的API端点测试控制器。我的RSpec Controller测试仪如下:

require 'rails_helper'
require 'spec_helper'
require 'rack/test'
require 'devise'

class RoutesControllerTest < ActionController::TestCase

  describe "User with token"
    test "should post route" do  
      params = { route: {  start_lat: 38.7627951, start_long: -9.1532211,
                            end_lat: 38.7483783, end_long: -9.155045,
                            flag_opt: 0.4, city: 1 }
                }

      post '/routes.json' , params.to_json, format: :json
      assert_response :success
    end
  end
end

我的控制器是:

class RoutesController < ApplicationController

  def create
    city = City.find(params[:route][:city])
    user = current_user
    @route = user.routes.new(route_params)
    @results = @route.calc_route(@route.start_long, @route.start_lat, @route.end_long, @route.end_lat, params[:route][:flag_opt], city)
    if @route.save!
      render :template=>"/routes/routes.json.jbuilder", status: 201, :formats => [:json]
    else
      render json: @route.errors
    end
  end

  private

  def route_params
    json_params = ActionController::Parameters.new( JSON.parse(request.body.read) )
    json_params.require(:route).permit(
          :start_lat, 
          :start_long, 
          :end_lat, 
          :end_long,
          :flag_opt
     )
  end
end

但每次我运行rspec spec/controller时我都会遇到以下错误:

Failure/Error: json_params = ActionController::Parameters.new(JSON.parse(request.body.read) )

JSON::ParserError:
  757: unexpected token at 'route%5Bcity%5D=24&route%5Bend_lat%5D=41.26171490000001&route%5Bend_long%5D=-8.38193640000001&route%5Bflag_opt%5D=1&route%5Bstart_lat%5D=38.753225&route%5Bstart_long%5D=-9.144376&route%5Buser_id%5D=24'

这意味着请求不是作为JSON发送的

6 个答案:

答案 0 :(得分:3)

我也一直在努力挣扎。有时您真的只想用一个真实的JSON主体进行测试。我不确定该解决方案是否特定于Rails 5,但是经过大量的探索,我终于松了一口气,终于找到了解决方案。

您可以使用as: :json代替format: :json使RSpec格式化请求正文。

也就是说,更改:

post '/routes.json' , params.to_json, format: :json

post '/routes.json' , params.to_json, as: :json

答案 1 :(得分:1)

我很好奇你为什么要做json_params = ActionController::Parameters.new( JSON.parse(request.body.read)? (我错过了什么吗?)

params应该已经作为ActionContoller :: Parameters进入。所以,route_params应该是

def route_params
  params.require(:route).permit(
    :start_lat, 
    :start_long, 
    :end_lat, 
    :end_long,
    :flag_opt
   )
end

顺便说一下,我假设您的routes.rb类似于

# config/routes.rb
Rails.application.routes.draw do     
  namespace :api, defaults: {format: 'json'} do
    ...
  end
end

答案 2 :(得分:1)

这对我来说测试了发布到控制器上的json(RSpec 3.7.0)

post :action, params: { whatever: value }, body: { some_key: value }.to_json, as: :json

然后您使用以下命令读取了控制器

request.body.read

答案 3 :(得分:0)

您需要将JSON解析设置为您的测试环境。

在spec / support / request_helper.rb中创建一个文件:

module Requests
  module JsonHelpers
    def json
      @json ||= JSON.parse(response.body)
    end
  end
end

RSpec.configure do |config|
  config.include Requests::JsonHelpers, type: :controller
end

并且

答案 4 :(得分:0)

我不确定为什么你的API必须在其创建动作中接收json。这就是我要做的事情:

var domain = ConfigurationManager.AppSettings["GlimpseVersionCheckAPIDomain"];

        if (string.IsNullOrEmpty(domain))
        {
            domain = "getGlimpse.com";
        }

        return new CacheControlDecorator(OneDay, CacheSetting.Public, new RedirectResourceResult(@"//" + domain + "/Api/Version/Check{?packages*}{&stamp}{&callback}", data));

然后在你强大的参数中:

class RoutesControllerTest < ActionController::TestCase

  describe "User with token"
    test "should post route" do  
      params = { route: {  start_lat: 38.7627951, start_long: -9.1532211,
                            end_lat: 38.7483783, end_long: -9.155045,
                            flag_opt: 0.4, city: 1 }
                }

      count = Route.all.size

      post :create, params
      expect(response).to have_http_status(201)
      expect(Route.all.size).to eq(count + 1) # actually created something
    end
  end
end

即使在rails端也不需要像JSON一样处理所有内容。

答案 5 :(得分:0)

对于Rails 5,只需在HTTP动词之前调用request.accept = "application/json"。示例:

context "GET #show" do
  it "returns json data" do
    request.accept = "application/json"
    get :show
    hash_body = JSON.parse(response.body)
    #### your expectation here
  end
end