如何测试Controller post:使用rspec在rails上创建JSON api?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何测试Controller post:使用rspec在rails上创建JSON api?相关的知识,希望对你有一定的参考价值。

我一直在撕破我的头发,试图通过测试。我有一个看起来像这样的JSON API:

{
  "data": [
    {
      "id": "b99f8173-0492-457f-9de9-6c1d8d6832ed",
      "type": "manufacturer_organizations",
      "attributes": {
        "account_number": "random test 123"
      },
      "relationships": {
        "organization": {
          "data": {
            "id": "fb20ddc9-a3ee-47c3-bdd2-f710541ff89c",
            "type": "organizations"
          }
        },
        "manufacturer": {
          "data": {
            "id": "1",
            "type": "manufacturers"
          }
        }
      }
    },...

我试图在rails中进行post :create测试。

let!(:manufacturer_organization) {FactoryGirl.create(:manufacturer_organization)}
let(:manufacturer_organization2) { FactoryGirl.create(:manufacturer_organization)}

...

  describe "POST create" do
    it "posts a valid manufacturer organization data" do
      authenticate
      organization = FactoryGirl.create(:organization)
      manufacturer = FactoryGirl.create(:manufacturer)

      post :create, manufacturer_organization2.to_json #what should I put here instead?

      expect(json['data'].length).to eq(2)
    end

  #=> error: JSON::ParserError: A JSON text must at least contain two octets!

我尝试了各种SO帖子(this)thisthis article

以下是我尝试过的一些尝试:

post :create, params: {organization_id: organization.id, manufacturer: manufacturer.id, account_number: "123 test account number"}
#=> error: JSON::ParserError:
   A JSON text must at least contain two octets!

要么

post :create, params: :manufacturer_organization_2
#=> 
 NoMethodError:
   undefined method `symbolize_keys' for :manufacturer_organization_2:Symbol

要么

json = { :format => 'json', :manufacturer_organization => { :account_number => "foo123", :organization_id => organization.id, :manufacturer_id => manufacturer.id } }
post :create, json
#=>  NoMethodError:
   undefined method `length' for nil:NilClass 

如何通过q​​azxswpoi测试我的控制器接受manufacturer_id, organization_id, and account_number?现在我测试的方式是计算初始post :create(最初为1);最后,我预计json['data'].length在成功的json['data'].length之后是2。如何模拟创建有效的manufacturer_organization输入?

编辑:

对不起,忘了把我的json方法助手:

post :create

此外,这个传球:

def json
  JSON.parse(response.body)
end

而添加 describe "POST create" do it "posts a valid manufacturer organization data" do authenticate organization = FactoryGirl.create(:organization) manufacturer = FactoryGirl.create(:manufacturer) post :create, {account_number: "Test account numba", organization_id: organization.id, manufacturer_id: manufacturer.id} expect(response).to be_success end 给了我这个错误:

expect(json['success']).to eq("Yay!")

控制器:

JSON::ParserError:
       A JSON text must at least contain two octets!

def create @manufacturer_organization = ManufacturerOrganization.new(manufacturer_organization_params) if @manufacturer_organization.save puts "success!" render json: {success: "Yay!"} else puts "Sorry, something went wrong!" end end def manufacturer_organization_params api_params.permit(:organization_id, :manufacturer_id, :account_number) end

答案

在RSpec中,您永远不需要明确格式化参数。

@api_params ||= ActionController::Parameters.new(ActiveModelSerializers::Deserialization.jsonapi_parse(params))

这将在请求正文中将散列post :create, params: { foo: 'bar' }, format: :json 正确格式化为JSON。

要创建与JSONAPI.org结构匹配的哈希,您可以创建一个帮助程序:

{ foo: 'bar' }

您还可以使用JSONAPI-RB gem或ActiveModel :: Serializers来构造/解构JSONAPI响应/参数。


# support/api_spec_helper.rb
module APISpecHelper
  def to_json_api(model)
    {
      data: {
        type: ActiveModel::Naming.plural(model),
        attributes: model.attributes
      }.tap do |hash| 
        hash[:id] = model.id if model.persisted?
      end
    }
  end
end

返回正确的状态代码。

返回正确的响应代码非常简单:

require 'rails_helper'
require 'api_spec_helper'

RSpec.request "Manufacturer organizations" do 

  include APISpecHelper

  describe "POST '/manufacturer_organizations'" do
    let(:valid_params) do
      to_json_api(FactoryGirl.build(:manufacturer_organization))
    end
    let(:invalid_params) do
      to_json_api(ManufacturerOrganization.new(
        foo: 'bad_value'
      ))
    end

    describe "with valid attributes" do
      it "creates a manufacturer organization" do
        expect do
          post '/manufacturer_organizations', params: valid_params, format: :json
        end.to change(ManufacturerOrganization, :count).by(+1)
      end

      it "has the correct response" do
        post '/manufacturer_organizations', params: valid_params, format: :json
        expect(response).to have_status :created
        expect(response.headers[:location]).to eq(
          manufacturer_organization_path(ManufacturerOrganization.last)
        )
      end
    end

    describe "with valid attributes" do
      it "does not create a manufacturer organization" do
        expect do
          post '/manufacturer_organizations', params: invalid_params, format: :json
        end.to_not change(ManufacturerOrganization, :count)
      end

      it "has the correct response" do
        post '/manufacturer_organizations', params: invalid_params, format: :json
        expect(response).to have_status :unproccessable_entity
      end
    end
  end
end

如果POST请求未包含客户端生成的ID并且已成功创建所请求的资源,则服务器必须返回201 Created状态代码。 def create @resource = Resource.create(some_params) if @resource.save # you can respond by pointing at the newly created resource but with no body head :created, location: @resource # or render json: @resource, status: :created, location: @resource else render json: { errors: @resource.errors.full_messages }, status: :unprocessable_entity end end

其他回应 服务器可以使用其他HTTP状态代码进行响应。 服务器可能包含错误详细信息和错误响应。

普遍接受的做法是使用http://jsonapi.org/format/#crud进行验证错误。

一个小问题是你应该使用422 - Unprocessable Entity来提供正确的JSON响应,并序列化a serializer

以上是关于如何测试Controller post:使用rspec在rails上创建JSON api?的主要内容,如果未能解决你的问题,请参考以下文章

Wordpress 如何使用 WP_REST_Posts_Controller 获取特定的帖子数据

请教python 采 集 requests post请求一个第三方接口中文乱码的问题

访问taotao-portal 中controller中返回taotaoresult 测试httppost方法 出现406错误

AOSP 构建系统如何生成 .rsp 文件以及如何获取它们?

使用 PHPUnit 发送 POST 请求

使用Restlet Client发送各种Get和Post请求