Last Updated: February 25, 2016
·
930
· ktusznio

Using Rspec's shared_examples to spec new behavior

Suppose we have a CartController and a corresponding spec. At the moment, only logged-in users can add items to their carts, and we want to support carts for guest users.

So far, the spec might look like this:

describe CartController do
 let(:user) { create(:user) }
 let(:item) { create(:item) }
 let(:response_items) { JSON.parse(response["items"]) }

 describe :index do
 it "returns items in the cart" do
 user.cart.add(item)

 get :index

 response_items[0]["id"].should == item.id
 end
 end

 describe :create do
 it "adds an item to the cart" do
 post :create, id: item.id

 response_items[0]["id"].should == item.id
 end
 end

 describe :destroy do
 it "removes an item from the cart" do
 user.cart.add(item)

 delete :destroy, id: item.id

 response_items.should be_empty
 end
 end
end

Now, to add support for guest carts, it might be tempting to add stuff like:

it "adds an item to the cart when user is a guest"
it "removes an item to the cart when user is a guest"

But that will end up repeating a lot of the previous specs. It's important to isolate what's really changing, which is the user. So, let's set up some context blocks for the two scenarios:

context "signed in user" do
 let(:user) { create(:user) }
end

context "guest user" do
 let(:user) { User.new }
end

Now, we just need our previous specs to run in these two contexts. We can do that by moving them into shared examples and running those examples in our contexts:

shared_examples "cart requests" do
 describe :index
 describe :create
 describe :destroy
end

context "signed in user" do
 let(:user) { create(:user) }

 it_behaves_like "cart requests"
end

context "guest user" do
 let(:user) { User.new }

 it_behaves_like "cart requests"
end

With this approach, we've added a whole new layer of behavior to our specs with very little repetition or actual code.

And most importantly, since we've reused the previous specs, we can be certain that all of the functionality a real user has is also available to guest users.