1class MockObject 2 def initialize(name, options={}) 3 @name = name 4 @null = options[:null_object] 5 end 6 7 def method_missing(sym, *args, &block) 8 @null ? self : super 9 end 10 private :method_missing 11end 12 13class NumericMockObject < Numeric 14 def initialize(name, options={}) 15 @name = name 16 @null = options[:null_object] 17 end 18 19 def method_missing(sym, *args, &block) 20 @null ? self : super 21 end 22 23 def singleton_method_added(val) 24 end 25end 26 27class MockIntObject 28 def initialize(val) 29 @value = val 30 @calls = 0 31 32 key = [self, :to_int] 33 34 Mock.objects[key] = self 35 Mock.mocks[key] << self 36 end 37 38 attr_reader :calls 39 40 def to_int 41 @calls += 1 42 @value.to_int 43 end 44 45 def count 46 [:at_least, 1] 47 end 48end 49 50class MockProxy 51 attr_reader :raising, :yielding 52 53 def initialize(type=nil) 54 @multiple_returns = nil 55 @returning = nil 56 @raising = nil 57 @yielding = [] 58 @arguments = :any_args 59 @type = type || :mock 60 end 61 62 def mock? 63 @type == :mock 64 end 65 66 def stub? 67 @type == :stub 68 end 69 70 def count 71 @count ||= mock? ? [:exactly, 1] : [:any_number_of_times, 0] 72 end 73 74 def arguments 75 @arguments 76 end 77 78 def returning 79 if @multiple_returns 80 if @returning.size == 1 81 @multiple_returns = false 82 return @returning = @returning.shift 83 end 84 return @returning.shift 85 end 86 @returning 87 end 88 89 def times 90 self 91 end 92 93 def calls 94 @calls ||= 0 95 end 96 97 def called 98 @calls = calls + 1 99 end 100 101 def exactly(n) 102 @count = [:exactly, n_times(n)] 103 self 104 end 105 106 def at_least(n) 107 @count = [:at_least, n_times(n)] 108 self 109 end 110 111 def at_most(n) 112 @count = [:at_most, n_times(n)] 113 self 114 end 115 116 def once 117 exactly 1 118 end 119 120 def twice 121 exactly 2 122 end 123 124 def any_number_of_times 125 @count = [:any_number_of_times, 0] 126 self 127 end 128 129 def with(*args) 130 raise ArgumentError, "you must specify the expected arguments" if args.empty? 131 if args.length == 1 132 @arguments = args.first 133 else 134 @arguments = args 135 end 136 self 137 end 138 139 def and_return(*args) 140 case args.size 141 when 0 142 @returning = nil 143 when 1 144 @returning = args[0] 145 else 146 @multiple_returns = true 147 @returning = args 148 count[1] = args.size if count[1] < args.size 149 end 150 self 151 end 152 153 def and_raise(exception) 154 if exception.kind_of? String 155 @raising = RuntimeError.new exception 156 else 157 @raising = exception 158 end 159 end 160 161 def raising? 162 @raising != nil 163 end 164 165 def and_yield(*args) 166 @yielding << args 167 self 168 end 169 170 def yielding? 171 !@yielding.empty? 172 end 173 174 private 175 176 def n_times(n) 177 case n 178 when :once 179 1 180 when :twice 181 2 182 else 183 Integer n 184 end 185 end 186end 187