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
2 Answers 2
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
-
2\$\begingroup\$ You could also make
response
the subject, and thus writeits(:response_code) { should == 200 }
\$\endgroup\$Flambino– Flambino2013年02月24日 06:34:01 +00:00Commented Feb 24, 2013 at 6:34
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.