Skip to content

Instantly share code, notes, and snippets.

@floere
Created January 28, 2010 13:29
Show Gist options
  • Save floere/288737 to your computer and use it in GitHub Desktop.
Save floere/288737 to your computer and use it in GitHub Desktop.
ministubs, based on nikos ministubs
require 'rubygems'
require 'minitest/unit'
require 'minitest/spec'
MiniTest::Unit.autorun
# This walks the given stub strings and sets up partial stub responder chains.
#
class StubBuilder
attr_reader :__next__
def initialize __response__
@__response__ = __response__
end
# Generates a stub call chain in the given call tree.
#
def __visit__ stub
if @__next__.__next__
@__next__.__visit__(stub.__call_tree[@__key__] = Stub.new(@__response__))
else
stub.__call_tree[@__key__] = @__response__
end
end
# This method missing is used to recognize and set up stub call chains.
#
def method_missing name, *args, &block
@__key__ = [name.to_s, args, block]
@__next__ = StubBuilder.new @__response__
end
end
# This is the Responder class.
#
module PartialStub
attr_reader :__call_tree
attr_writer :__next__
def initialize response = nil
@__call_tree = {}
@__response__ = response
end
# def get_binding block, builder, method_call
# Proc.new do
#
# end.binding
# return binding
# end
# Initializer method.
#
def stub method_hash
@__call_tree ||= {}
method_hash.each do |method_call, response|
builder = StubBuilder.new response
if method_call.is_a? Proc
# eval "builder.instance_eval method_call.to_s", get_binding(block, builder, method_call)
builder.instance_eval &method_call
else
builder.instance_eval method_call.to_s
end
builder.__visit__ self
end
end
# This method missing is used to respond to stub calls.
#
def method_missing name, *args, &block
@__call_tree[[name.to_s, args, block]]
end
end
class Stub
include PartialStub
end
describe MiniTest::Spec do
before do
@s = Object.new
@s.extend PartialStub
end
alias l lambda
it 'should handle itself' do
@s.stub :identity => @s
@s.identity.must_equal @s
end
it 'should handle an explicit nil' do
@s.stub :bla => nil
@s.bla.must_equal nil
end
it 'should handle strange method names' do
@s.stub :_? => :_
@s._?.must_equal :_
end
it 'should add new methods' do
@s.stub :bla => 1
@s.bla.must_equal 1
end
# it 'should handles blocks' do
# block = lambda { |bla| bla**2 }
# @s.stub 'bla(&block)' => 1
# @s.bla(&block).must_equal 1
# end
it 'should work with the cool parentheses-less style' do
@s.stub "bla 5" => 5
(@s.bla 5).must_equal 5
end
it 'should add new methods with args' do
@s.stub "bla(5)" => 5
@s.bla(5).must_equal 5
end
it 'should take two methods' do
@s.stub 'bla(4)' => 4, 'bla(5)' => 5
@s.bla(4).must_equal 4
@s.bla(5).must_equal 5
end
it 'should take methods with and without arguments' do
@s.stub 'bla' => 2, 'bla(5)' => 5
@s.bla.must_equal 2
@s.bla(5).must_equal 5
end
it 'should work with more than one argument' do
@s.stub 'bla(5,3)' => 5
@s.bla(5,3).must_equal 5
end
it 'should work with evaluated arguments' do
@s.stub :'bla(4**2,3)' => 5
@s.bla(16,3).must_equal 5
end
it 'should work with question marks' do
@s.stub 'bla?' => :yes
@s.bla?.must_equal :yes
end
it 'should work with bangs' do
@s.stub 'bla!' => 5
@s.bla!.must_equal 5
end
it 'should work with symbol definitions' do
@s.stub :bla! => 5
@s.bla!.must_equal 5
end
it 'should work with variables as results' do
# Note: This test has been changed compared to the original.
# I want to be able to test against easily recognizable symbols.
#
@r = 'fu'
r = 'raa!'
@s.stub "bla(1)" => @r, "blub(2)" => r, 'bra' => 'bra', "bra('what')" => :a
@s.bla(1).must_equal @r
@s.blub(2).must_equal r
@s.bra.must_equal 'bra'
@s.bra('what').must_equal :a
end
it 'should work with demeter calls' do
@s.stub 'bla(2,3,4).blub(3,4,5)' => 5
@s.bla(2,3,4).blub(3,4,5).must_equal 5
end
it 'should fail correctly' do
@s.stub 'bla(2,3,4).blub(3,4)' => 5
@s.bla(2,3,4).blub(3,4,5).must_equal nil
end
# it 'should work with assignments, use self' do
# @s.stub 'self.bla=(6)' => 'a'
# (@s.bla = 6).must_equal 'a'
# end
it 'should work with local variables as args' do
r = 'fu'
s = 'raa!'
@s.stub l{ bla(r) } => 5, l{ blub(s) } => 'b'
@s.bla("fu").must_equal 5
@s.blub(s).must_equal 'b'
end
# it 'should work with instance variables as args' do
# @r = 'fu'
# s = 'raa!'
# @s.stub l{bla(@r)} => 5, l{blub(s)} => 'b'
# @s.bla("fu").must_equal 5
# @s.blub(s).must_equal 'b'
# end
it 'should work with other objects' do
a = Class.new.new
@s.stub l{ blub(a) } => a
@s.blub(a).must_equal a
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment