How to test Controller post :create of JSON api on rails using rspec?

前端 未结 1 1840
-上瘾入骨i
-上瘾入骨i 2021-01-07 11:01

I have been tearing my hair trying to make the test to pass. I have a JSON API that looks like this:

{
  \"data\": [
    {
      \"id\": \"b99f8173-0492-457f         


        
相关标签:
1条回答
  • 2021-01-07 11:52

    In RSpec you never* need to explicitly format the params.

    post :create, params: { foo: 'bar' }, format: :json
    

    This will properly format the hash { foo: 'bar' } as JSON in the request body.

    To create a hash which matches the JSONAPI.org structure you can create a helper:

    # 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
    

    You can also use the JSONAPI-RB gem or ActiveModel::Serializers to 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
    

    Returning the correct status codes.

    Returning the correct response codes is pretty simple:

    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.

    The commonly accepted practice is to use 422 - Unprocessable Entity for validation errors.

    One small concern is that you should use a serializer to give the correct JSON response and also serialize the correct error objects.

    0 讨论(0)
提交回复
热议问题