Class/Module Index [+]

Quicksearch

RSpec::Core::MemoizedHelpers::ClassMethods

This module is extended onto {ExampleGroup}, making the methods available to be called from within example group blocks. You can think of them as being analagous to class macros.

Public Instance Methods

let(name, &block) click to toggle source

Generates a method whose return value is memoized after the first call. Useful for reducing duplication between examples that assign values to the same local variable.

@note `let` can enhance readability when used sparingly (1,2, or

maybe 3 declarations) in any given example group, but that can
quickly degrade with overuse. YMMV.

@note `let` uses an `||=` conditional that has the potential to

behave in surprising ways in examples that spawn separate threads,
though we have yet to see this in practice. You've been warned.

@note Because `let` is designed to create state that is reset between

each example, and `before(:context)` is designed to setup state that is
shared across _all_ examples in an example group, `let` is _not_
intended to be used in a `before(:context)` hook.

@example

describe Thing do
  let(:thing) { Thing.new }

  it "does something" do
    # first invocation, executes block, memoizes and returns result
    thing.do_something

    # second invocation, returns the memoized value
    thing.should be_something
  end
end
# File lib/rspec/core/memoized_helpers.rb, line 231
def let(name, &block)
  # We have to pass the block directly to `define_method` to
  # allow it to use method constructs like `super` and `return`.
  raise "#let or #subject called without a block" if block.nil?
  MemoizedHelpers.module_for(self).__send__(:define_method, name, &block)

  # Apply the memoization. The method has been defined in an ancestor
  # module so we can use `super` here to get the value.
  if block.arity == 1
    define_method(name) { __memoized.fetch(name) { |k| __memoized[k] = super(RSpec.current_example, &nil) } }
  else
    define_method(name) { __memoized.fetch(name) { |k| __memoized[k] = super(&nil) } }
  end
end
let!(name, &block) click to toggle source

Just like `let`, except the block is invoked by an implicit `before` hook. This serves a dual purpose of setting up state and providing a memoized reference to that state.

@example

class Thing
  def self.count
    @count ||= 0
  end

  def self.count=(val)
    @count += val
  end

  def self.reset_count
    @count = 0
  end

  def initialize
    self.class.count += 1
  end
end

describe Thing do
  after(:example) { Thing.reset_count }

  context "using let" do
    let(:thing) { Thing.new }

    it "is not invoked implicitly" do
      Thing.count.should eq(0)
    end

    it "can be invoked explicitly" do
      thing
      Thing.count.should eq(1)
    end
  end

  context "using let!" do
    let!(:thing) { Thing.new }

    it "is invoked implicitly" do
      Thing.count.should eq(1)
    end

    it "returns memoized version on first invocation" do
      thing
      Thing.count.should eq(1)
    end
  end
end
# File lib/rspec/core/memoized_helpers.rb, line 299
def let!(name, &block)
  let(name, &block)
  before { __send__(name) }
end
subject(name=nil, &block) click to toggle source

Declares a `subject` for an example group which can then be wrapped with `expect` using `is_expected` to make it the target of an expectation in a concise, one-line example.

Given a `name`, defines a method with that name which returns the `subject`. This lets you declare the subject once and access it implicitly in one-liners and explicitly using an intention revealing name.

@param name [String,Symbol] used to define an accessor with an

intention revealing name

@param block defines the value to be returned by `subject` in examples

@example

describe CheckingAccount, "with $50" do
  subject { CheckingAccount.new(Money.new(50, :USD)) }
  it { is_expected.to have_a_balance_of(Money.new(50, :USD)) }
  it { is_expected.not_to be_overdrawn }
end

describe CheckingAccount, "with a non-zero starting balance" do
  subject(:account) { CheckingAccount.new(Money.new(50, :USD)) }
  it { is_expected.not_to be_overdrawn }
  it "has a balance equal to the starting balance" do
    account.balance.should eq(Money.new(50, :USD))
  end
end

@see MemoizedHelpers#should @see MemoizedHelpers#should_not @see MemoizedHelpers#is_expected

# File lib/rspec/core/memoized_helpers.rb, line 336
def subject(name=nil, &block)
  if name
    let(name, &block)
    alias_method :subject, name

    self::NamedSubjectPreventSuper.__send__(:define_method, name) do
      raise NotImplementedError, "`super` in named subjects is not supported"
    end
  else
    let(:subject, &block)
  end
end
subject!(name=nil, &block) click to toggle source

Just like `subject`, except the block is invoked by an implicit `before` hook. This serves a dual purpose of setting up state and providing a memoized reference to that state.

@example

class Thing
  def self.count
    @count ||= 0
  end

  def self.count=(val)
    @count += val
  end

  def self.reset_count
    @count = 0
  end

  def initialize
    self.class.count += 1
  end
end

describe Thing do
  after(:example) { Thing.reset_count }

  context "using subject" do
    subject { Thing.new }

    it "is not invoked implicitly" do
      Thing.count.should eq(0)
    end

    it "can be invoked explicitly" do
      subject
      Thing.count.should eq(1)
    end
  end

  context "using subject!" do
    subject!(:thing) { Thing.new }

    it "is invoked implicitly" do
      Thing.count.should eq(1)
    end

    it "returns memoized version on first invocation" do
      subject
      Thing.count.should eq(1)
    end
  end
end
# File lib/rspec/core/memoized_helpers.rb, line 402
def subject!(name=nil, &block)
  subject(name, &block)
  before { subject }
end

[Validate]

Generated with the Darkfish Rdoc Generator 2.