3
\$\begingroup\$

The Model is simple: a Player class with three attributes: first_name, last_name, and team_id.

I'm just trying to get a handle on TDD for what will expand into a much more robust API. Here is my first stab at the integration/controller specs for REST actions on the API.

I haven't seen a lot of concrete examples of RSpec and API tests, so feedback is very welcome.

I'm using Rabl in my views for rendering the JSON Responses.

describe Api::V1::PlayersController do
 render_views
 before do
 @player1 = FactoryGirl.create(:player, first_name: "Joe", last_name: "Smith", team_id: 1)
 @player2 = FactoryGirl.create(:player, first_name: "Bob", last_name: "Jones", team_id: 2)
 @player3 = FactoryGirl.create(:player, first_name: "Peter", last_name: "Wilson", team_id: 3)
 end
 describe "#index" do
 before do
 get :index, :format => :json
 end
 it "should retrieve status code of 200" do
 response.response_code.should == 200
 end
 it "should retrieve license header" do
 response.header["X-LS-License"].should == "All Rights Reserved"
 end
 it "should retrieve application name header" do
 response.header["X-LS-Application"].should == "league-server"
 end
 it "should retrieve records-returned header" do
 response.header["X-LS-Records-Returned"].should be_present
 end
 it "should retrieve a content-type of json" do
 response.header['Content-Type'].should include 'application/json'
 end
 it "should retrieve list of players" do
 players = Player.all
 players.count.should == 3
 response.body.should include(@player1.id.to_s)
 response.body.should include(@player2.id.to_s)
 response.body.should include(@player3.id.to_s)
 response.body.should include('Joe Smith')
 response.body.should include('Bob Jones')
 response.body.should include('Peter Wilson')
 end
 end
 describe "#show" do
 before do
 get :show, id: @player1.id, :format => :json
 end
 it "should retrieve status code of 200" do
 response.response_code.should == 200
 end
 it "should retrieve application name header" do
 response.header["X-LS-Application"].should == "league-server"
 end
 it "should retrieve license header" do
 response.header["X-LS-License"].should == "All Rights Reserved"
 end
 it "should retrieve records-returned header" do
 response.header["X-LS-Records-Returned"].should == "1"
 end
 it "should retrieve a content-type of json" do
 response.header['Content-Type'].should include 'application/json'
 end
 it "should retrieve a single player" do
 player = Player.where id: @player1.id
 player.count.should == 1
 response.body.should include(@player1.id.to_s)
 response.body.should include('Joe Smith')
 end
 end
 describe "#create" do
 before do
 request_payload = {
 player: {
 first_name: "Buck",
 last_name: "Carradine",
 team_id: "1",
 junk: "trunk"
 }
 }
 post :create, request_payload
 end
 it "should retrieve status code of 200" do
 response.response_code.should == 200
 end
 it "should retrieve application name header" do
 response.header["X-LS-Application"].should == "league-server"
 end
 it "should retrieve license header" do
 response.header["X-LS-License"].should == "All Rights Reserved"
 end
 it "should retrieve records-returned header" do
 response.header["X-LS-Records-Returned"].should == "1"
 end
 it "should retrieve a content-type of json" do
 response.header['Content-Type'].should include 'application/json'
 end
 it "should retrieve a single player" do
 response.body.should include('Buck Carradine')
 end
 it "should not add extraneous attributes" do
 response.body.should_not include('junk')
 end
 end
 describe "#update" do
 before do
 request_payload = {
 player: {
 first_name: "Buck",
 last_name: "Carradine",
 team_id: "1"
 }
 }
 put :update, { id: @player1.id }.merge(request_payload)
 end
 it "should retrieve status code of 200" do
 response.response_code.should == 200
 end
 it "should retrieve application name header" do
 response.header["X-LS-Application"].should == "league-server"
 end
 it "should retrieve license header" do
 response.header["X-LS-License"].should == "All Rights Reserved"
 end
 it "should retrieve records-returned header" do
 response.header["X-LS-Records-Returned"].should == "1"
 end
 it "should retrieve a content-type of json" do
 response.header['Content-Type'].should include 'application/json'
 end
 it "should retrieve a single player" do
 response.body.should include('Buck')
 response.body.should_not include('Joe')
 end
 end
 describe "#delete" do
 before do
 delete :destroy, id: @player1.id
 end
 it "should retrieve status code of 200" do
 response.response_code.should == 200
 end
 it "should retrieve application name header" do
 response.header["X-LS-Application"].should == "league-server"
 end
 it "should retrieve license header" do
 response.header["X-LS-License"].should == "All Rights Reserved"
 end
 it "should retrieve records-returned header" do
 response.header["X-LS-Records-Returned"].should == "0"
 end
 it "should retrieve a content-type of json" do
 response.header['Content-Type'].should include 'application/json'
 end
 it "should retrieve a single player" do
 response.body.should include('Player deleted')
 end
 end
end
Jamal
35.2k13 gold badges134 silver badges238 bronze badges
asked Oct 24, 2012 at 2:43
\$\endgroup\$

2 Answers 2

3
\$\begingroup\$

You might consider replacing this:

it "should retrieve status code of 200" do
 response.response_code.should == 200
end

with

it { response.response_code.should == 200 }

I find that very simple code checks are better done with the second form to eliminate duplication when you're reading the test.

It's helpful to review this occasionally. Something good is added frequently.

Quote from https://github.com/rspec/rspec-expectations

One-liners

The one-liner syntax supported by rspec-core uses should even when config.syntax = :expect. It reads better than the alternative, and does not require a global monkey patch:

describe User do it { should validate_presence_of :email } end

This is another helpful reference: https://www.relishapp.com/rspec/rspec-rails/v/2-13/docs/controller-specs

answered Feb 24, 2013 at 4:57
\$\endgroup\$
1
  • 2
    \$\begingroup\$ You could also make response the subject, and thus write its(:response_code) { should == 200 } \$\endgroup\$ Commented Feb 24, 2013 at 6:34
2
\$\begingroup\$

This looks pretty okay to me. I don't see why you have multiple header data tests though, I would assume they are all generated through the same piece of code, so you should either remove redundant tests to DRY up your specs, or if you are not using the same bit of code to generate the headers refactor that instead.

Regarding your initial question, I do not feel that API testing is any different that any other request and controller testing.

answered Nov 9, 2012 at 23:13
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.