module Shoulda::Matchers::Independent

This module provides matchers that are used to test behavior outside of Rails-specific classes.

Public Instance Methods

delegate_method(delegating_method) click to toggle source

The ‘delegate_method` matcher tests that an object forwards messages to other, internal objects by way of delegation.

In this example, we test that Courier forwards a call to deliver onto its PostOffice instance:

require 'forwardable'

class Courier
  extend Forwardable

  attr_reader :post_office

  def_delegators :post_office, :deliver

  def initialize
    @post_office = PostOffice.new
  end
end

# RSpec
describe Courier do
  it { should delegate_method(:deliver).to(:post_office) }
end

# Minitest
class CourierTest < Minitest::Test
  should delegate_method(:deliver).to(:post_office)
end

You can also use ‘delegate_method` with Rails’s ‘delegate` macro:

class Courier
  attr_reader :post_office
  delegate :deliver, to: :post_office

  def initialize
    @post_office = PostOffice.new
  end
end

describe Courier do
  it { should delegate_method(:deliver).to(:post_office) }
end

To employ some terminology, we would say that Courier’s deliver method is the *delegating method*, PostOffice is the *delegate object*, and PostOffice#deliver is the *delegate method*.

#### Qualifiers

##### as

Use ‘as` if the name of the delegate method is different from the name of the delegating method.

Here, Courier has a deliver method, but instead of calling deliver on the PostOffice, it calls ship:

class Courier
  attr_reader :post_office

  def initialize
    @post_office = PostOffice.new
  end

  def deliver(package)
    post_office.ship(package)
  end
end

# RSpec
describe Courier do
  it { should delegate_method(:deliver).to(:post_office).as(:ship) }
end

# Minitest
class CourierTest < Minitest::Test
  should delegate_method(:deliver).to(:post_office).as(:ship)
end

##### with_prefix

Use ‘with_prefix` when using Rails’s ‘delegate` helper along with the `:prefix` option.

class Page < ActiveRecord::Base
  belongs_to :site
  delegate :name, to: :site, prefix: true
  delegate :title, to: :site, prefix: :root
end

# RSpec
describe Page do
  it { should delegate_method(:name).to(:site).with_prefix }
  it { should delegate_method(:name).to(:site).with_prefix(true) }
  it { should delegate_method(:title).to(:site).with_prefix(:root) }
end

# Minitest
class PageTest < Minitest::Test
  should delegate_method(:name).to(:site).with_prefix
  should delegate_method(:name).to(:site).with_prefix(true)
  should delegate_method(:title).to(:site).with_prefix(:root)
end

##### with_arguments

Use ‘with_arguments` to assert that the delegate method is called with certain arguments. Note that this qualifier can only be used when the delegating method takes no arguments; it does not support delegating or delegate methods that take arbitrary arguments.

Here, when Courier#deliver_package calls PostOffice#deliver_package, it adds an options hash:

class Courier
  attr_reader :post_office

  def initialize
    @post_office = PostOffice.new
  end

  def deliver_package
    post_office.deliver_package(expedited: true)
  end
end

# RSpec
describe Courier do
  it do
    should delegate_method(:deliver_package).
      to(:post_office).
      with_arguments(expedited: true)
  end
end

# Minitest
class CourierTest < Minitest::Test
  should delegate_method(:deliver_package).
    to(:post_office).
    with_arguments(expedited: true)
end

##### allow_nil

Use ‘allow_nil` if the delegation accounts for the fact that your delegate object could be nil. (This is mostly intended as an analogue to the `allow_nil` option that Rails’ ‘delegate` helper takes.)

class Account
  delegate :plan, to: :subscription, allow_nil: true
end

# RSpec
describe Account do
  it { should delegate_method(:plan).to(:subscription).allow_nil }
end

# Minitest
class PageTest < Minitest::Test
  should delegate_method(:plan).to(:subscription).allow_nil
end

@return [DelegateMethodMatcher]

# File lib/shoulda/matchers/independent/delegate_method_matcher.rb, line 173
def delegate_method(delegating_method)
  DelegateMethodMatcher.new(delegating_method).in_context(self)
end