Skip to content

Instantly share code, notes, and snippets.

@shipstar
Forked from swanson/test-stub.rb
Created March 5, 2012 21:48
Show Gist options
  • Save shipstar/1981349 to your computer and use it in GitHub Desktop.
Save shipstar/1981349 to your computer and use it in GitHub Desktop.
Toy stub framework with Ruby
# Playing around with a Toy Stubbing "framework"
class Statistics
def initialize(nums)
@nums = nums
end
def compute_average
sum = 0;
@nums.each do |num|
sum += num
end
sum.to_f / @nums.length
end
end
module Stub
def self.extended(base)
klass = base.class
methods_to_stub = klass.instance_methods - Object.instance_methods
klass.instance_eval do
methods_to_stub.each { |m| undef_method m unless m =~ /(^__|^send$|^object_id$)/ }
end
base.instance_eval{ @canned_responses = {} }
end
def method_missing(m, *args, &block)
if @canned_responses.has_key?(m)
@canned_responses[m]
else
raise "Unstubbed method!"
end
end
def canned(m, ret)
@canned_responses[m] = ret
end
end
s = Statistics.new(nil)
s.extend Stub
s.canned(:compute_average, 6.5)
p "The average is: #{s.compute_average}"
@shipstar
Copy link
Author

shipstar commented Mar 5, 2012

I'm not in love with this implementation (especially having to lazy initialize canned_responses), and I'm probably missing some tricks on self.extended, but this seems to work as a module.

@swanson
Copy link

swanson commented Mar 5, 2012

Neat! Is the canned_responses method a convention? Or because there is no initializer in the Stub module?

I was closer than I thought on my initial stab at least :)

@shipstar
Copy link
Author

shipstar commented Mar 5, 2012

It's a bit of a convention, but it's mostly because I didn't have access to initialize in the module. Upon further reflection, I could've done:

base.instance_eval{ @canned_responses = {} }

in self.extended, then used @canned_responses as in your original. I'll modify the Gist now.

Metaprogramming is something I need to spend more time on myself. I know most of the methods exist, but there's always a bit of "Should I be class_evaling or instance_evaling?" when I use them.

@swanson
Copy link

swanson commented Mar 5, 2012

"Upon further reflection" - I see what you did there ;-P

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment