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 
\$\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

    \$\endgroup\$
    1
    • 2
      \$\begingroup\$You could also make response the subject, and thus write its(:response_code) { should == 200 }\$\endgroup\$
      – Flambino
      CommentedFeb 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.

    \$\endgroup\$

      Start asking to get answers

      Find the answer to your question by asking.

      Ask question

      Explore related questions

      See similar questions with these tags.