/usr/lib/ruby/vendor_ruby/minitest/mock.rb is in ruby-minitest 5.2.1-1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
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 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 | class MockExpectationError < StandardError; end # :nodoc:
module Minitest # :nodoc:
##
# A simple and clean mock object framework.
#
# All mock objects are an instance of Mock
class Mock
alias :__respond_to? :respond_to?
overridden_methods = %w(
===
inspect
object_id
public_send
respond_to_missing?
send
to_s
)
instance_methods.each do |m|
undef_method m unless overridden_methods.include?(m.to_s) || m =~ /^__/
end
overridden_methods.map(&:to_sym).each do |method_id|
define_method method_id do |*args, &b|
if @expected_calls.has_key? method_id then
method_missing(method_id, *args, &b)
else
super(*args, &b)
end
end
end
def initialize # :nodoc:
@expected_calls = Hash.new { |calls, name| calls[name] = [] }
@actual_calls = Hash.new { |calls, name| calls[name] = [] }
end
##
# Expect that method +name+ is called, optionally with +args+ or a
# +blk+, and returns +retval+.
#
# @mock.expect(:meaning_of_life, 42)
# @mock.meaning_of_life # => 42
#
# @mock.expect(:do_something_with, true, [some_obj, true])
# @mock.do_something_with(some_obj, true) # => true
#
# @mock.expect(:do_something_else, true) do |a1, a2|
# a1 == "buggs" && a2 == :bunny
# end
#
# +args+ is compared to the expected args using case equality (ie, the
# '===' operator), allowing for less specific expectations.
#
# @mock.expect(:uses_any_string, true, [String])
# @mock.uses_any_string("foo") # => true
# @mock.verify # => true
#
# @mock.expect(:uses_one_string, true, ["foo"])
# @mock.uses_one_string("bar") # => true
# @mock.verify # => raises MockExpectationError
def expect(name, retval, args=[], &blk)
name = name.to_sym
if block_given?
raise ArgumentError, "args ignored when block given" unless args.empty?
@expected_calls[name] << { :retval => retval, :block => blk }
else
raise ArgumentError, "args must be an array" unless Array === args
@expected_calls[name] << { :retval => retval, :args => args }
end
self
end
def __call name, data # :nodoc:
case data
when Hash then
"#{name}(#{data[:args].inspect[1..-2]}) => #{data[:retval].inspect}"
else
data.map { |d| __call name, d }.join ", "
end
end
##
# Verify that all methods were called as expected. Raises
# +MockExpectationError+ if the mock object was not called as
# expected.
def verify
@expected_calls.each do |name, calls|
calls.each do |expected|
msg1 = "expected #{__call name, expected}"
msg2 = "#{msg1}, got [#{__call name, @actual_calls[name]}]"
raise MockExpectationError, msg2 if
@actual_calls.has_key?(name) and
not @actual_calls[name].include?(expected)
raise MockExpectationError, msg1 unless
@actual_calls.has_key?(name) and
@actual_calls[name].include?(expected)
end
end
true
end
def method_missing(sym, *args) # :nodoc:
unless @expected_calls.has_key?(sym) then
raise NoMethodError, "unmocked method %p, expected one of %p" %
[sym, @expected_calls.keys.sort_by(&:to_s)]
end
index = @actual_calls[sym].length
expected_call = @expected_calls[sym][index]
unless expected_call then
raise MockExpectationError, "No more expects available for %p: %p" %
[sym, args]
end
expected_args, retval, val_block =
expected_call.values_at(:args, :retval, :block)
if val_block then
raise MockExpectationError, "mocked method %p failed block w/ %p" %
[sym, args] unless val_block.call(args)
# keep "verify" happy
@actual_calls[sym] << expected_call
return retval
end
if expected_args.size != args.size then
raise ArgumentError, "mocked method %p expects %d arguments, got %d" %
[sym, expected_args.size, args.size]
end
fully_matched = expected_args.zip(args).all? { |mod, a|
mod === a or mod == a
}
unless fully_matched then
raise MockExpectationError, "mocked method %p called with unexpected arguments %p" %
[sym, args]
end
@actual_calls[sym] << {
:retval => retval,
:args => expected_args.zip(args).map { |mod, a| mod === a ? mod : a }
}
retval
end
def respond_to?(sym, include_private = false) # :nodoc:
return true if @expected_calls.has_key? sym.to_sym
return __respond_to?(sym, include_private)
end
end
end
class Object # :nodoc:
##
# Add a temporary stubbed method replacing +name+ for the duration
# of the +block+. If +val_or_callable+ responds to #call, then it
# returns the result of calling it, otherwise returns the value
# as-is. If stubbed method yields a block, +block_args+ will be
# passed along. Cleans up the stub at the end of the +block+. The
# method +name+ must exist before stubbing.
#
# def test_stale_eh
# obj_under_test = Something.new
# refute obj_under_test.stale?
#
# Time.stub :now, Time.at(0) do
# assert obj_under_test.stale?
# end
# end
#
def stub name, val_or_callable, *block_args, &block
new_name = "__minitest_stub__#{name}"
metaclass = class << self; self; end
if respond_to? name and not methods.map(&:to_s).include? name.to_s then
metaclass.send :define_method, name do |*args|
super(*args)
end
end
metaclass.send :alias_method, new_name, name
metaclass.send :define_method, name do |*args, &blk|
ret = if val_or_callable.respond_to? :call then
val_or_callable.call(*args)
else
val_or_callable
end
blk.call(*block_args) if blk
ret
end
yield self
ensure
metaclass.send :undef_method, name
metaclass.send :alias_method, name, new_name
metaclass.send :undef_method, new_name
end
end
|