Created
January 28, 2010 13:29
-
-
Save floere/288737 to your computer and use it in GitHub Desktop.
ministubs, based on nikos ministubs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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