How can I validate each item in an array using RSpec's shared example groups?
I'm building a rest-ish JSON API using Rails, and I'd like to test the resource representations I'm getting back from the server.
I want to validate the response in multiple places, so I created a shared example group that describes the stuff I expect to have inside a single resource. It looks something like this:
describe "Widget API" do
shared_examples_for "a widget resource" do
subject { resource }
its ['id'] { should == widget.id }
its ['name'] { should == widget.name }
its ['owner'] { should == widget.owner }
end
describe "a GET request to /widgets/:id" do
before(:each) do
@widget = Factory(:widget)
get widget_path(@widget)
end
it_behaves_like "a widget resource" do
let(:widget) { @widget }
let(:resource) { ActiveSupport::JSON.decode(response.body.strip) }
end
end
end
A request is made, and the shared example group is called with both the hashified response body and the original widget object so they can be compared.
This is working pretty well, and I only have one spot to update my tests if I need to add/change something in the widget representation.
The problem I'm having is when I want to validate an arbitrarily sized array of widget resources, say, for example when requesting the index action:
describe "a GET request to /widgets" do
before(:each) do
@widgets = [Factory(:widget), Factory(:widget), Factory(:widget)]
get widgets_path
end
### Something like this would be nice:
it "responds with an array of widgets" do
@resources = ActiveSupport::JSON.decode(response.body.strip)
@widgets.each_with_index 开发者_StackOverflow社区do |widget, index|
it_behaves_like "a widget resource" do
let(:widget) { widget }
let(:resource) { @resources[index] }
end
end
end
end
(This is a bit contrived, but I think it sorta describes what I'm looking for.)
The problem above is that the it_behaves_like
method isn't available within the context of an it
block, so I get NoMethodErrors thrown at me.
Is there any way to do this type of enumerating over a subject and calling a shared example group on each of the subject's elements? Am I way off base here? Is there a better way to structure this?
Thanks for any suggestions!
-John
精彩评论