Class: QuacksLike

Inherits:
Object
  • Object
show all
Defined in:
lib/quacks_like.rb

Overview

QuacksLike is a module for RSpec to add matchers that test if an object is fully duck-typed to pretend to be another class. This kind of thing is really only necessary when passing such an object as the return value in an API where you don't know exactly how it will be consumed, but it needs to "quack like an Array" or something. It does its job by checking every instance method in the class that the target object needs to "quack like" and makes sure the target both responds to that method name and that the arity of the method is appropriate.

Usage (in RSpec files):

require 'quacks_like'

it "should return an object that quacks like a Hash" do
my_func.should quack_like_a(Hash)
end

it "should return an object that does not quack like an Array" do
my_func.should_not quack_like_an(Array)
end

Instance Method Summary collapse

Constructor Details

#initialize(quack_class) ⇒ QuacksLike

Returns a new instance of QuacksLike.



28
29
30
# File 'lib/quacks_like.rb', line 28

def initialize (quack_class)
  @quack_class = quack_class
end

Instance Method Details

#failure_message_for_shouldObject



58
59
60
# File 'lib/quacks_like.rb', line 58

def failure_message_for_should
  [@target.inspect, @mismatches.join(', ')].join(' ')
end

#failure_message_for_should_notObject



62
63
64
# File 'lib/quacks_like.rb', line 62

def failure_message_for_should_not
  "expected #{@target.inspect} to not quack like a(n) #{@quack_class.inspect}"
end

#matches?(target) ⇒ Boolean

Returns:

  • (Boolean)


41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
# File 'lib/quacks_like.rb', line 41

def matches? (target)
  @target = target
  @mismatches = []

  @quack_class.instance_methods.each do |m|
    if not @target.respond_to?(m)
      @mismatches.push "does not respond to :#{m}"
    elsif not arity_compare(q = @quack_class.instance_method(m).arity,
                            t = @target.method(m).arity)
      @mismatches.
          push "quacking method :#{m} has arity #{q} but found arity #{t}"
    end
  end

  @mismatches.empty?
end