Nappstir
Nappstir

Reputation: 995

Rails API rspec tests

I'm building an API where Users can follow and be followed by other Users. I have created a Relationship table to handle the associations along with Relationship endpoints. Here is my endpoint for following someone:

def create
 user = User.find(params[:followed_id])
 if user
   current_user.follow(user)
   render json: [current_user, Relationship.where(followed_id: user.id, follower_id: current_user.id)], status: 201, location: [:api, current_user]
 else
   render json: { errors: current_user.errors }, status: 422
 end
end

Everything is working as intended. As you can see, I want to respond with my current_user object and the newly created Relationship object. Both of which work when I hit this endpoint providing an Authorization token and the id of the user I want to follow. The issue that I am having is testing that I get back a Relationship object. Here are the tests I have for the following endpoint:

describe "POST #create" do

 context "When relationship is successfully created" do
   before(:each) do
     @user = FactoryGirl.create(:user)
     other_user = FactoryGirl.create(:user)
     api_authorization_header(@user.auth_token)
     post :create, followed_id: other_user.id
   end

   it "should respond w/ current_user object" do
     user_response = JSON.parse(response.body, symbolize_names: true)
     expect(user_response[0][:id]).to eq(@user.id)
   end

### THIS TEST IS FAILING & THE ONE THAT I NEED HELP WITH.
   it "should respond w/ created relationship object" do
     user_response = JSON.parse(response.body, symbolize_names: true)
     expect(user_response[1]).to be_kind_of(Relationship)
   end

   it { should respond_with(201) }
 end

end

Here are some outputs of user_response:

user_response = {:id=>1233, :email=>"[email protected]", :first_name=>"Marcelina", :last_name=>"Morissette", :created_at=>"2016-03-28T18:16:09.875Z", :updated_at=>"2016-03-28T18:16:09.875Z", :auth_token=>"Ky25sYoJc4gH-p122yEH"}
{:id=>150, :follower_id=>1233, :followed_id=>1234, :created_at=>"2016-03-28T18:16:09.892Z", :updated_at=>"2016-03-28T18:16:09.892Z"}

You can see user_response is returning an array of the two objects I asked it to respond to.

user_response[1] = {:id=>150, :follower_id=>1233, :followed_id=>1234, :created_at=>"2016-03-28T18:16:09.892Z", :updated_at=>"2016-03-28T18:16:09.892Z"}

Here is there error I receive when trying to run `expect(user_response[1]).to be_kind_of(Relationship)

1) Api::V1::RelationshipController POST #create When relationship is successfully created should respond w/ created relationship object
 Failure/Error: expect(user_response[1]).to be_kind_of(Relationship)
   expected [{:id=>153, :follower_id=>1239, :followed_id=>1240, :created_at=>"2016-03-28T18:18:43.064Z", :updated_at=>"2016-03-28T18:18:43.064Z"}] to be a kind of Relationship(id: integer, follower_id: integer, followed_id: integer, created_at: datetime, updated_at: datetime)
 # ./spec/controllers/api/v1/relationship_controller_spec.rb:27:in `block (4 levels) in <top (required)>'

Any suggestions on how I can test that the second object being sent back is an object from the Relationship class? Also, if there is a more 'correct' way for handling this endpoint, I would appreciate the lesson =).

Upvotes: 2

Views: 596

Answers (1)

aarkerio
aarkerio

Reputation: 2364

"create" method is returning a JSON response, not an ActiveRecord Object. An HTTP response can't be "be_kind_of(Relationship)". JSON is just formatted text.

If you are building a RESTful API you must be testing the JSON responses and the HTTP status in the requests, and not testing the controllers. Something like:

it 'updates a user on update_user action' do
  params = {
    id:     @user.id,  # FactoryGirl object
    fname: 'John',
    lname: 'Smith',
    email: '[email protected]'
  }

  post '/v1/users/update', params, @env

  # test for the 200 status-code
  expect(response).to be_success
  expect(json['data']['email']).to eq '[email protected]'
end   

BTW, you shouldn't be using sessions in your API. Instead send your user id as a param in your request.

http://matthewlehner.net/rails-api-testing-guidelines/

Upvotes: 1

Related Questions