forked from rubinius/rubinius
-
Notifications
You must be signed in to change notification settings - Fork 0
/
missing.rb
68 lines (60 loc) · 1.3 KB
/
missing.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
# Records missing calls and dumps them at the end.
# Execute with
# -rmissing -e '$early = true' script.rb
# to have it raise NoMethodError, otherwise it continues,
# passing a mock down, gathering up missing behavior.
#
unless defined? $early
$early = false
end
MissedCalls = []
class MissedCall
def initialize(recv, name, args)
@recv, @name = recv.inspect, name
if args.empty?
@args = nil
else
@args = args.map { |i| i.inspect }.join(", ")
end
@sub_calls = []
end
def method_missing(meth, *args)
if args.empty?
args = nil
else
args = args.map { |i| i.inspect }.join(", ")
end
@sub_calls << [meth, args]
self
end
def show
print "#{@recv}.#{@name}"
if @args
puts ": #{@args}"
else
puts " (no args)"
end
@sub_calls.each do |meth, args|
print " #{meth}"
if args
puts ": #{args}"
else
puts " (no args)"
end
end
end
end
class Object
def method_missing(meth, *args)
obj = MissedCall.new(self, meth, args)
MissedCalls << obj
if $early
raise NoMethodError, "Couldn't find a '#{meth}' on a #{self.inspect}"
end
obj
end
end
at_exit do
print "\nDetected #{MissedCalls.size} missed calls.\n\n"
MissedCalls.each { |c| c.show }
end