Shared Helpers

Has there been any development on shared helpers / it_should_behave_like
feature in rspec?

I forget the reasons, but I remember a patch for something like this was
rejected:

it_should_behave_like "an_entry", :locals => { :entry => Entry.new }

OR:

before do
  @entry = Entry.new
end

it_should_behave_like "an_entry", :locals => lambda {
  {
    :entry => @entry
  }
}

Is there any code which now deals with the variable passing issue in
rspec?

Best,

Scott

On 23 Feb 2010, at 17:30, Scott T. wrote:

OR:

Is there any code which now deals with the variable passing issue in
rspec?

Best,

Scott

FWIW, what I’ve done in this situation is expect that the ExampleGroup
I’ve mixed the shared behaviour into to define a method, and call that
from the shared examples - if it’s not defined you’ll find out pretty
quickly. Another approach is to just expect the @variable to be set:

describe “an entry” do
before
@entry or raise(“You need to set @entry to use this shared
example group”)
end
end

It’s not great, but it makes the shared example group a little more
self-documenting than if you just shared the instance variable without
the check.

cheers,
Matt

+447974 430184

I just use a factory method.

describe ‘Authorize.net CIM gateway’, :shared => true do
describe ‘saving a card’ do
describe ‘preconditions’ do
it “should raise an error if the card is not saved” do
lambda {
gateway.save_credit_card(Factory.build(:credit_card, :user =>
Factory(:user)))
}.should raise_error(ArgumentError, /unsaved record/)
end
end

describe 'first card saved on an account' do
  it "should set the authorize_id on the credit card" do
    credit_card = Factory :credit_card, :user => Factory(:user)
    gateway.save_credit_card credit_card
    credit_card.authorize_id.should be_present
  end

  it "should return true for a successful response" do
    credit_card = Factory :credit_card, :user => Factory(:user)
    gateway.save_credit_card(credit_card).should be_true
  end

  it "should mark the card as having a validated card code" do
    card = Factory :credit_card, :card_code_validated => false
    gateway.save_credit_card card
    card.should be_card_code_validated
  end
end

etc etc etc etc

end
end

describe Payment::AuthorizeNetCim::FakeGateway do
def gateway
@gateway ||= Payment::AuthorizeNetCim::FakeGateway.new
end

it_should_behave_like ‘Authorize.net CIM gateway’

some extra custom examples

end

I prefer this to requiring an instance variable, because you get built
in error-handling for free. If you don’t implement the factory method,
you get “undefined method: gateway” rather than the less obvious
undefined method on NilClass error.

Also, your :locals => { :entry => Entry.new } syntax is going to be no
good because you’ll only have one instance of Entry that gets reused
across examples. No bueno. You’d have to do
:locals => lambda { { :entry => Entry.new } }
and now it’s just getting ugly.

If you think defining methods is too heavy (which I wouldn’t agree with,
but okay) then maybe use the let method?

describe Entry do
before do
let(:entry) { Entry.new )
end

it_should_behave_like “an_entry”
end

How’s that look?

Pat

On Tue, Feb 23, 2010 at 3:41 PM, Matt W. [email protected] wrote:

it_should_behave_like “an_entry”, :locals => { :entry => Entry.new }
}
mixed the shared behaviour into to define a method, and call that from the
It’s not great, but it makes the shared example group a little more
self-documenting than if you just shared the instance variable without the
check.

cheers,
Matt

We do what Matt does, plus we document on top of the shared examples
the interface the example group needs:

You need to provide an <invalid_record> method that returns a record

without

saving, in an invalid state, for this mixin to work.

shared_examples_for “a model that can disable validations” do
context “when checking for a record’s validity” do
it “always returns true if you disabled validations” do
described_class.disable_validations!
invalid_record.should be_valid
end

it "falls back to the usual behavior if you enable validations" do
  described_class.enable_validations!
  invalid_record.should_not be_valid
end

end


end

describe User do
let :invalid_record do
User.make_unsaved(:invalid)
end

it_should_behave_like “a model that can disable validations”
end

Cheers,
-foca