Class: Object

Inherits:
BasicObject
Defined in:
lib/stump/metaid.rb,
lib/stump/mock.rb,
lib/stump/stub.rb,
lib/stump/proxy.rb,
lib/stump/metareset.rb

Overview

Instance Method Summary collapse

Instance Method Details

#class_def(name, &blk) ⇒ Object

Defines an instance method within a class



18
19
20
# File 'lib/stump/metaid.rb', line 18

def class_def name, &blk
  class_eval { define_method name, &blk }
end

#meta_def(name, &blk) ⇒ Object

Adds methods to a metaclass



9
10
11
12
13
14
15
# File 'lib/stump/metaid.rb', line 9

def meta_def name, &blk
  meta_eval {
    define_method(name) {|*args, &block|
      blk.call(*args, &block)
    }
  }
end

#meta_eval(&blk) ⇒ Object



6
# File 'lib/stump/metaid.rb', line 6

def meta_eval &blk; metaclass.instance_eval &blk; end

#metaclassObject

The hidden singleton lurks behind everyone



5
# File 'lib/stump/metaid.rb', line 5

def metaclass; class << self; self; end; end

#mock!(method, options = {}, &block) ⇒ Object

Create a mock method on an object. A mock object will place an expectation on behavior and cause a test failure if it’s not fulfilled.

Examples

my_string = "a wooden rabbit"
my_string.mock!(:retreat!, :return => "run away!  run away!")
my_string.mock!(:question, :return => "what is the airspeed velocity of an unladen sparrow?")

# test/your_test.rb
my_string.retreat!    # => "run away!  run away!"
# If we let the test case end at this point, it fails with:
# Unmet expectation: #<Sparrow:1ee7> expected question


16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
# File 'lib/stump/mock.rb', line 16

def mock!(method, options = {}, &block)
  Stump::Mocks.add([self, method])

  behavior =  if block_given?
                lambda do |*args|
                  raise ArgumentError if block.arity >= 0 && args.length != block.arity

                  Stump::Mocks.verify([self, method])
                  block.call(*args)
                end
              elsif !options[:yield].nil?
                lambda do |*args|
                  Stump::Mocks.verify([self, method])
                  yield(options[:yield])
                end
              else
                lambda do |*args|
                  Stump::Mocks.verify([self, method])
                  return options[:return]
                end
              end

  safe_meta_def method, &behavior
end

#proxy!(method, options = {}, &block) ⇒ Object

Creates a proxy method on an object. In this setup, it places an expectation on an object (like a mock) but still calls the original method. So if you want to make sure the method is called and still return its value, or simply want to invoke the side effects of a method and return a stubbed value, then you can do that.

Examples

class Parrot
  def speak!
    puts @words
  end

  def say_this(words)
    @words = words
    "I shall say #{words}!"
  end
end

# => test/your_test.rb
sqawky = Parrot.new
sqawky.proxy!(:say_this)
# Proxy method still calls original method...
sqawky.say_this("hey")   # => "I shall say hey!"
sqawky.speak!            # => "hey"

sqawky.proxy!(:say_this, "herro!")
# Even though we return a stubbed value...
sqawky.say_this("these words")   # => "herro!"
# ...the side effects are still there.
sqawky.speak!                    # => "these words"

TODO: This implementation is still very rough. Needs refactoring and refining. Won’t work on ActiveRecord attributes, for example.



36
37
38
39
40
41
42
43
44
# File 'lib/stump/proxy.rb', line 36

def proxy!(method, options = {}, &block)
  Stump::Mocks.add([self, method])
  
  if respond_to?(method)
    proxy_existing_method(method, options, &block)
  else
    proxy_missing_method(method, options, &block)
  end
end

#reset(method_name) ⇒ Object



11
12
13
# File 'lib/stump/metareset.rb', line 11

def reset(method_name)
  metaclass.restore_original_method(method_name)
end

#safe_meta_def(method_name, &method_body) ⇒ Object



2
3
4
5
6
7
8
9
# File 'lib/stump/metareset.rb', line 2

def safe_meta_def method_name, &method_body
  metaclass.remember_original_method(method_name)
  meta_eval {
    define_method(method_name) {|*args, &block|
      method_body.call(*args, &block)
    }
  }
end

#should_not_call(method) ⇒ Object



41
42
43
44
45
46
# File 'lib/stump/mock.rb', line 41

def should_not_call(method)
  behavior =  lambda do |*args|
                should.flunk "Umet expectations: #{method} expected to not be called"
              end
  safe_meta_def method, &behavior
end

#stub!(method_name, options = {}, &stubbed) ⇒ Object

Create a stub method on an object. Simply returns a value for a method call on an object.

Examples

my_string = "a wooden rabbit"
my_string.stub!(:retreat!, :return => "run away!  run away!")

# test/your_test.rb
my_string.retreat!    # => "run away!  run away!"


13
14
15
16
17
# File 'lib/stump/stub.rb', line 13

def stub!(method_name, options = {}, &stubbed)
  behavior = (block_given? ? stubbed : lambda { return options[:return] })

  safe_meta_def method_name, &behavior
end