如何测试 Controller post :create of JSON api on rails using rspec?
How to test Controller post :create of JSON api on rails using rspec?
为了通过考试,我一直在焦头烂额。我有一个 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), this, and this 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
如何测试我的控制器以通过 post :create
接受 manufacturer_id, organization_id, and account_number
?现在我测试它的方式是计算 initial json['data'].length
(最初是 1);最后我希望 json['data'].length
在成功 post :create
后为 2。我如何模拟创建有效的 manufacturer_organization 输入?
编辑:
抱歉,忘了放我的 json 方法助手:
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
同时 @api_params ||= ActionController::Parameters.new(ActiveModelSerializers::Deserialization.jsonapi_parse(params))
在 RSpec 中,您永远*不需要明确格式化参数。
post :create, params: { foo: 'bar' }, format: :json
这将在请求正文中将散列 { foo: 'bar' }
正确格式化为 JSON。
要创建一个与 JSONAPI.org 结构匹配的散列,您可以创建一个助手:
# 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
您还可以使用 JSONAPI-RB gem 或 ActiveModel::Serializers 到 constuct/deconstruct JSONAPI responses/params.
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
正在返回正确的状态代码。
返回正确的响应代码非常简单:
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
If a POST request did not include a Client-Generated ID and the
requested resource has been created successfully, the server MUST
return a 201 Created status code.
http://jsonapi.org/format/#crud
Other Responses
A server MAY respond with other HTTP status codes.
A server MAY include error details with error responses.
普遍接受的做法是对验证错误使用422 - Unprocessable Entity。
一个小问题是您应该使用 a serializer to give the correct JSON response and also serialize the correct error objects。
为了通过考试,我一直在焦头烂额。我有一个 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), this, and this 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
如何测试我的控制器以通过 post :create
接受 manufacturer_id, organization_id, and account_number
?现在我测试它的方式是计算 initial json['data'].length
(最初是 1);最后我希望 json['data'].length
在成功 post :create
后为 2。我如何模拟创建有效的 manufacturer_organization 输入?
编辑:
抱歉,忘了放我的 json 方法助手:
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
同时 @api_params ||= ActionController::Parameters.new(ActiveModelSerializers::Deserialization.jsonapi_parse(params))
在 RSpec 中,您永远*不需要明确格式化参数。
post :create, params: { foo: 'bar' }, format: :json
这将在请求正文中将散列 { foo: 'bar' }
正确格式化为 JSON。
要创建一个与 JSONAPI.org 结构匹配的散列,您可以创建一个助手:
# 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
您还可以使用 JSONAPI-RB gem 或 ActiveModel::Serializers 到 constuct/deconstruct JSONAPI responses/params.
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
正在返回正确的状态代码。
返回正确的响应代码非常简单:
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
If a POST request did not include a Client-Generated ID and the requested resource has been created successfully, the server MUST return a 201 Created status code.
http://jsonapi.org/format/#crudOther Responses
A server MAY respond with other HTTP status codes.
A server MAY include error details with error responses.
普遍接受的做法是对验证错误使用422 - Unprocessable Entity。
一个小问题是您应该使用 a serializer to give the correct JSON response and also serialize the correct error objects。