DiegoFrings
DiegoFrings

Reputation: 3115

How can I use RSpec Expectations in PORO's

Hi,

I am trying to DRY up some of my specs. I extracted an Assertion class that does a couple of shoulds ... but most of the RSpec expectation magic is not working anymore.

I'll try to construct a simple example, to show my problem.

The object under test:

class Foo
  def has_bar?; true; end
end

My assertion class:

class MyAssertions
  def self.assert_everything_is_ok
    @foo = Foo.new
    @foo.has_bar?.should == true  # works!
    @foo.has_bar?.should be_true  # undefined local variable or method `be_true`
    @foo.should have_bar          # undefined local variable or method `have_bar`
  end
end

My spec:

it "tests something" do
  @foo = Foo.new
  @foo.should have_bar                # works!
  MyAssertion.assert_everything_is_ok # does not work, because of errors above
end

Why can I not use the syntactic sugar of rspec expectations in my plain old ruby object?

Upvotes: 2

Views: 642

Answers (2)

zetetic
zetetic

Reputation: 47568

A more 'RSpec-like' way to do this is with a custom matcher:

RSpec::Matchers.define :act_like_a_good_foo do
  match do
    # subject is implicit in example
    subject.has_bar?.should == true
    subject.should be_true  # predicate matchers defined within RSpec::Matchers
    subject.should have_bar
  end
end

describe Foo do
  it { should act_like_a_good_foo }
end

Upvotes: 2

DiegoFrings
DiegoFrings

Reputation: 3115

After some more trying I came up with this solution:

class MyAssertions
  include RSpec::Matchers

  def assert_everything_is_ok
    @foo = Foo.new
    @foo.has_bar?.should == true  # works!
    @foo.has_bar?.should be_true  # works now :)
    @foo.should have_bar          # works now :)
  end
end

The trick was to include the RSpec::Matchers module. And I had use instance methods instead of class methods.

Upvotes: 2

Related Questions