jferris-rr 0.7.1.0.1239654108

Sign up to get free protection for your applications and to get access to all the features.
Files changed (130) hide show
  1. data/CHANGES +196 -0
  2. data/README.rdoc +329 -0
  3. data/Rakefile +77 -0
  4. data/lib/rr.rb +84 -0
  5. data/lib/rr/adapters/rr_methods.rb +122 -0
  6. data/lib/rr/adapters/rspec.rb +58 -0
  7. data/lib/rr/adapters/test_unit.rb +29 -0
  8. data/lib/rr/double.rb +212 -0
  9. data/lib/rr/double_definitions/child_double_definition_creator.rb +27 -0
  10. data/lib/rr/double_definitions/double_definition.rb +346 -0
  11. data/lib/rr/double_definitions/double_definition_creator.rb +167 -0
  12. data/lib/rr/double_definitions/double_definition_creator_proxy.rb +37 -0
  13. data/lib/rr/double_definitions/strategies/implementation/implementation_strategy.rb +15 -0
  14. data/lib/rr/double_definitions/strategies/implementation/proxy.rb +62 -0
  15. data/lib/rr/double_definitions/strategies/implementation/reimplementation.rb +14 -0
  16. data/lib/rr/double_definitions/strategies/implementation/strongly_typed_reimplementation.rb +17 -0
  17. data/lib/rr/double_definitions/strategies/scope/instance.rb +15 -0
  18. data/lib/rr/double_definitions/strategies/scope/instance_of_class.rb +46 -0
  19. data/lib/rr/double_definitions/strategies/scope/scope_strategy.rb +15 -0
  20. data/lib/rr/double_definitions/strategies/strategy.rb +70 -0
  21. data/lib/rr/double_definitions/strategies/verification/dont_allow.rb +34 -0
  22. data/lib/rr/double_definitions/strategies/verification/mock.rb +44 -0
  23. data/lib/rr/double_definitions/strategies/verification/stub.rb +45 -0
  24. data/lib/rr/double_definitions/strategies/verification/verification_strategy.rb +15 -0
  25. data/lib/rr/double_injection.rb +143 -0
  26. data/lib/rr/double_matches.rb +51 -0
  27. data/lib/rr/errors/argument_equality_error.rb +6 -0
  28. data/lib/rr/errors/double_definition_error.rb +6 -0
  29. data/lib/rr/errors/double_not_found_error.rb +6 -0
  30. data/lib/rr/errors/double_order_error.rb +6 -0
  31. data/lib/rr/errors/rr_error.rb +20 -0
  32. data/lib/rr/errors/spy_verification_errors/double_injection_not_found_error.rb +8 -0
  33. data/lib/rr/errors/spy_verification_errors/invocation_count_error.rb +8 -0
  34. data/lib/rr/errors/spy_verification_errors/spy_verification_error.rb +8 -0
  35. data/lib/rr/errors/subject_does_not_implement_method_error.rb +6 -0
  36. data/lib/rr/errors/subject_has_different_arity_error.rb +6 -0
  37. data/lib/rr/errors/times_called_error.rb +6 -0
  38. data/lib/rr/expectations/any_argument_expectation.rb +21 -0
  39. data/lib/rr/expectations/argument_equality_expectation.rb +41 -0
  40. data/lib/rr/expectations/times_called_expectation.rb +57 -0
  41. data/lib/rr/hash_with_object_id_key.rb +41 -0
  42. data/lib/rr/recorded_calls.rb +103 -0
  43. data/lib/rr/space.rb +123 -0
  44. data/lib/rr/spy_verification.rb +48 -0
  45. data/lib/rr/spy_verification_proxy.rb +18 -0
  46. data/lib/rr/times_called_matchers/any_times_matcher.rb +18 -0
  47. data/lib/rr/times_called_matchers/at_least_matcher.rb +15 -0
  48. data/lib/rr/times_called_matchers/at_most_matcher.rb +23 -0
  49. data/lib/rr/times_called_matchers/integer_matcher.rb +19 -0
  50. data/lib/rr/times_called_matchers/non_terminal.rb +27 -0
  51. data/lib/rr/times_called_matchers/proc_matcher.rb +11 -0
  52. data/lib/rr/times_called_matchers/range_matcher.rb +21 -0
  53. data/lib/rr/times_called_matchers/terminal.rb +20 -0
  54. data/lib/rr/times_called_matchers/times_called_matcher.rb +44 -0
  55. data/lib/rr/wildcard_matchers/anything.rb +18 -0
  56. data/lib/rr/wildcard_matchers/boolean.rb +23 -0
  57. data/lib/rr/wildcard_matchers/duck_type.rb +32 -0
  58. data/lib/rr/wildcard_matchers/hash_including.rb +29 -0
  59. data/lib/rr/wildcard_matchers/is_a.rb +25 -0
  60. data/lib/rr/wildcard_matchers/numeric.rb +13 -0
  61. data/lib/rr/wildcard_matchers/range.rb +7 -0
  62. data/lib/rr/wildcard_matchers/regexp.rb +7 -0
  63. data/lib/rr/wildcard_matchers/satisfy.rb +26 -0
  64. data/spec/core_spec_suite.rb +19 -0
  65. data/spec/environment_fixture_setup.rb +6 -0
  66. data/spec/high_level_spec.rb +368 -0
  67. data/spec/rr/adapters/rr_methods_argument_matcher_spec.rb +67 -0
  68. data/spec/rr/adapters/rr_methods_creator_spec.rb +149 -0
  69. data/spec/rr/adapters/rr_methods_space_spec.rb +115 -0
  70. data/spec/rr/adapters/rr_methods_spec_helper.rb +11 -0
  71. data/spec/rr/adapters/rr_methods_times_matcher_spec.rb +17 -0
  72. data/spec/rr/double_definitions/child_double_definition_creator_spec.rb +112 -0
  73. data/spec/rr/double_definitions/double_definition_creator_proxy_spec.rb +155 -0
  74. data/spec/rr/double_definitions/double_definition_creator_spec.rb +502 -0
  75. data/spec/rr/double_definitions/double_definition_spec.rb +1159 -0
  76. data/spec/rr/double_injection/double_injection_bind_spec.rb +111 -0
  77. data/spec/rr/double_injection/double_injection_dispatching_spec.rb +244 -0
  78. data/spec/rr/double_injection/double_injection_has_original_method_spec.rb +55 -0
  79. data/spec/rr/double_injection/double_injection_reset_spec.rb +90 -0
  80. data/spec/rr/double_injection/double_injection_spec.rb +77 -0
  81. data/spec/rr/double_injection/double_injection_verify_spec.rb +29 -0
  82. data/spec/rr/double_spec.rb +352 -0
  83. data/spec/rr/errors/rr_error_spec.rb +67 -0
  84. data/spec/rr/expectations/any_argument_expectation_spec.rb +47 -0
  85. data/spec/rr/expectations/anything_argument_equality_expectation_spec.rb +14 -0
  86. data/spec/rr/expectations/argument_equality_expectation_spec.rb +135 -0
  87. data/spec/rr/expectations/boolean_argument_equality_expectation_spec.rb +34 -0
  88. data/spec/rr/expectations/hash_including_argument_equality_expectation_spec.rb +82 -0
  89. data/spec/rr/expectations/hash_including_spec.rb +17 -0
  90. data/spec/rr/expectations/satisfy_argument_equality_expectation_spec.rb +59 -0
  91. data/spec/rr/expectations/satisfy_spec.rb +14 -0
  92. data/spec/rr/expectations/times_called_expectation/times_called_expectation_any_times_spec.rb +46 -0
  93. data/spec/rr/expectations/times_called_expectation/times_called_expectation_at_least_spec.rb +69 -0
  94. data/spec/rr/expectations/times_called_expectation/times_called_expectation_at_most_spec.rb +71 -0
  95. data/spec/rr/expectations/times_called_expectation/times_called_expectation_helper.rb +23 -0
  96. data/spec/rr/expectations/times_called_expectation/times_called_expectation_integer_spec.rb +104 -0
  97. data/spec/rr/expectations/times_called_expectation/times_called_expectation_proc_spec.rb +81 -0
  98. data/spec/rr/expectations/times_called_expectation/times_called_expectation_range_spec.rb +83 -0
  99. data/spec/rr/expectations/times_called_expectation/times_called_expectation_spec.rb +38 -0
  100. data/spec/rr/rspec/invocation_matcher_spec.rb +279 -0
  101. data/spec/rr/rspec/rspec_adapter_spec.rb +66 -0
  102. data/spec/rr/rspec/rspec_backtrace_tweaking_spec.rb +31 -0
  103. data/spec/rr/rspec/rspec_backtrace_tweaking_spec_fixture.rb +11 -0
  104. data/spec/rr/rspec/rspec_usage_spec.rb +86 -0
  105. data/spec/rr/space/hash_with_object_id_key_spec.rb +88 -0
  106. data/spec/rr/space/space_spec.rb +542 -0
  107. data/spec/rr/test_unit/test_helper.rb +7 -0
  108. data/spec/rr/test_unit/test_unit_backtrace_test.rb +35 -0
  109. data/spec/rr/test_unit/test_unit_integration_test.rb +57 -0
  110. data/spec/rr/times_called_matchers/any_times_matcher_spec.rb +47 -0
  111. data/spec/rr/times_called_matchers/at_least_matcher_spec.rb +55 -0
  112. data/spec/rr/times_called_matchers/at_most_matcher_spec.rb +70 -0
  113. data/spec/rr/times_called_matchers/integer_matcher_spec.rb +70 -0
  114. data/spec/rr/times_called_matchers/proc_matcher_spec.rb +55 -0
  115. data/spec/rr/times_called_matchers/range_matcher_spec.rb +76 -0
  116. data/spec/rr/times_called_matchers/times_called_matcher_spec.rb +118 -0
  117. data/spec/rr/wildcard_matchers/anything_spec.rb +24 -0
  118. data/spec/rr/wildcard_matchers/boolean_spec.rb +36 -0
  119. data/spec/rr/wildcard_matchers/duck_type_spec.rb +52 -0
  120. data/spec/rr/wildcard_matchers/is_a_spec.rb +32 -0
  121. data/spec/rr/wildcard_matchers/numeric_spec.rb +32 -0
  122. data/spec/rr/wildcard_matchers/range_spec.rb +35 -0
  123. data/spec/rr/wildcard_matchers/regexp_spec.rb +43 -0
  124. data/spec/rr_spec.rb +28 -0
  125. data/spec/rspec_spec_suite.rb +16 -0
  126. data/spec/spec_helper.rb +107 -0
  127. data/spec/spec_suite.rb +27 -0
  128. data/spec/spy_verification_spec.rb +129 -0
  129. data/spec/test_unit_spec_suite.rb +21 -0
  130. metadata +187 -0
@@ -0,0 +1,44 @@
1
+ module RR
2
+ module TimesCalledMatchers
3
+ class TimesCalledMatcher #:nodoc:
4
+ class << self
5
+ def create(value)
6
+ return value if value.is_a?(TimesCalledMatcher)
7
+ return IntegerMatcher.new(value) if value.is_a?(Integer)
8
+ return RangeMatcher.new(value) if value.is_a?(Range )
9
+ return ProcMatcher.new(value) if value.is_a?(Proc)
10
+ raise ArgumentError, "There is no TimesCalledMatcher for #{value.inspect}."
11
+ end
12
+ end
13
+
14
+ attr_reader :times
15
+
16
+ def initialize(times)
17
+ @times = times
18
+ end
19
+
20
+ def matches?(times_called)
21
+ end
22
+
23
+ def attempt?(times_called)
24
+ end
25
+
26
+ def error_message(times_called)
27
+ "Called #{times_called.inspect} #{pluralized_time(times_called)}.\nExpected #{expected_times_message}."
28
+ end
29
+
30
+ def ==(other)
31
+ self.class == other.class && self.times == other.times
32
+ end
33
+
34
+ def expected_times_message
35
+ "#{@times.inspect} times"
36
+ end
37
+
38
+ protected
39
+ def pluralized_time(times_called)
40
+ (times_called == 1) ? "time" : "times"
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,18 @@
1
+ module RR
2
+ module WildcardMatchers
3
+ class Anything
4
+ def wildcard_match?(other)
5
+ true
6
+ end
7
+
8
+ def ==(other)
9
+ other.is_a?(self.class)
10
+ end
11
+ alias_method :eql?, :==
12
+
13
+ def inspect
14
+ 'anything'
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,23 @@
1
+ module RR
2
+ module WildcardMatchers
3
+ class Boolean
4
+ def wildcard_match?(other)
5
+ self == other || is_a_boolean?(other)
6
+ end
7
+
8
+ def ==(other)
9
+ other.is_a?(self.class)
10
+ end
11
+ alias_method :eql?, :==
12
+
13
+ def inspect
14
+ 'boolean'
15
+ end
16
+
17
+ protected
18
+ def is_a_boolean?(subject)
19
+ subject.is_a?(TrueClass) || subject.is_a?(FalseClass)
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,32 @@
1
+ module RR
2
+ module WildcardMatchers
3
+ class DuckType
4
+ attr_accessor :required_methods
5
+
6
+ def initialize(*required_methods)
7
+ @required_methods = required_methods
8
+ end
9
+
10
+ def wildcard_match?(other)
11
+ return true if self == other
12
+ required_methods.each do |m|
13
+ return false unless other.respond_to?(m)
14
+ end
15
+ return true
16
+ end
17
+
18
+ def inspect
19
+ formatted_required_methods = required_methods.collect do |method_name|
20
+ method_name.inspect
21
+ end.join(', ')
22
+ "duck_type(#{formatted_required_methods})"
23
+ end
24
+
25
+ def ==(other)
26
+ return false unless other.is_a?(self.class)
27
+ self.required_methods == other.required_methods
28
+ end
29
+ alias_method :eql?, :==
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,29 @@
1
+ module RR
2
+ module WildcardMatchers
3
+ class HashIncluding
4
+ attr_reader :expected_hash
5
+
6
+ def initialize(expected_hash)
7
+ @expected_hash = expected_hash.clone
8
+ end
9
+
10
+ def wildcard_match?(other)
11
+ return true if self == other
12
+ expected_hash.each_pair do |key, value|
13
+ return false unless other.has_key?(key) && other[key] == expected_hash[key]
14
+ end
15
+ return true
16
+ end
17
+
18
+ def inspect
19
+ "hash_including(#{expected_hash.inspect})"
20
+ end
21
+
22
+ def ==(other)
23
+ return false unless other.is_a?(self.class)
24
+ self.expected_hash == other.expected_hash
25
+ end
26
+ alias_method :eql?, :==
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,25 @@
1
+ module RR
2
+ module WildcardMatchers
3
+ class IsA
4
+ attr_reader :klass
5
+
6
+ def initialize(klass)
7
+ @klass = klass
8
+ end
9
+
10
+ def wildcard_match?(other)
11
+ self == other || other.is_a?(klass)
12
+ end
13
+
14
+ def inspect
15
+ "is_a(#{klass})"
16
+ end
17
+
18
+ def ==(other)
19
+ return false unless other.is_a?(self.class)
20
+ self.klass == other.klass
21
+ end
22
+ alias_method :eql?, :==
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,13 @@
1
+ module RR
2
+ module WildcardMatchers
3
+ class Numeric < IsA
4
+ def initialize
5
+ @klass = ::Numeric
6
+ end
7
+
8
+ def inspect
9
+ 'numeric'
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,7 @@
1
+ class Range
2
+ def wildcard_match?(other)
3
+ return true if self == other
4
+ return false unless other.is_a?(Numeric)
5
+ self.include?(other)
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ class Regexp
2
+ def wildcard_match?(other)
3
+ return true if self == other
4
+ return false unless other.is_a?(String)
5
+ (other =~ self) ? true : false
6
+ end
7
+ end
@@ -0,0 +1,26 @@
1
+ module RR
2
+ module WildcardMatchers
3
+ class Satisfy
4
+ attr_reader :expectation_proc
5
+
6
+ def initialize(expectation_proc)
7
+ @expectation_proc = expectation_proc
8
+ end
9
+
10
+ def wildcard_match?(other)
11
+ return true if self == other
12
+ !!expectation_proc.call(other)
13
+ end
14
+
15
+ def inspect
16
+ "satisfy {block}"
17
+ end
18
+
19
+ def ==(other)
20
+ return false unless other.is_a?(self.class)
21
+ self.expectation_proc == other.expectation_proc
22
+ end
23
+ alias_method :eql?, :==
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,19 @@
1
+ require "rubygems"
2
+ require "spec"
3
+
4
+ class CoreExampleSuite
5
+ def run
6
+ files = Dir["#{File.dirname(__FILE__)}/**/*_spec.rb"]
7
+ files.delete_if {|file| file.include?('rspec/')}
8
+ files.delete_if {|file| file.include?('test_unit/')}
9
+ puts "Running Rspec Example Suite"
10
+ files.each do |file|
11
+ require file
12
+ # puts "require '#{file}'"
13
+ end
14
+ end
15
+ end
16
+
17
+ if $0 == __FILE__
18
+ CoreExampleSuite.new.run
19
+ end
@@ -0,0 +1,6 @@
1
+ require "rubygems"
2
+ require "spec"
3
+ dir = File.dirname(__FILE__)
4
+ $LOAD_PATH.unshift "#{dir}/../lib"
5
+ require "rr"
6
+ require "pp"
@@ -0,0 +1,368 @@
1
+ require File.expand_path("#{File.dirname(__FILE__)}/spec_helper")
2
+
3
+ class HighLevelSpec
4
+ end
5
+
6
+ describe "RR" do
7
+ attr_reader :subject
8
+ before(:each) do
9
+ @subject = Object.new
10
+ extend RR::Adapters::RRMethods
11
+ end
12
+
13
+ after(:each) do
14
+ RR.reset
15
+ end
16
+
17
+ describe "mock" do
18
+ it "mocks via inline call" do
19
+ mock(subject).to_s {"a value"}
20
+ subject.to_s.should == "a value"
21
+ lambda {subject.to_s}.should raise_error(RR::Errors::TimesCalledError)
22
+ end
23
+
24
+ it "allows ordering" do
25
+ mock(subject).to_s {"value 1"}.ordered
26
+ mock(subject).to_s {"value 2"}.twice
27
+ subject.to_s.should == "value 1"
28
+ subject.to_s.should == "value 2"
29
+ subject.to_s.should == "value 2"
30
+ lambda {subject.to_s}.should raise_error(RR::Errors::TimesCalledError)
31
+ end
32
+
33
+ it 'allows terse chaining' do
34
+ mock(subject).first(1) {mock(Object.new).second(2) {mock(Object.new).third(3) {4}}}
35
+ subject.first(1).second(2).third(3).should == 4
36
+
37
+ mock(subject).first(1) {mock!.second(2) {mock!.third(3) {4}}}
38
+ subject.first(1).second(2).third(3).should == 4
39
+
40
+ mock(subject).first(1) {mock!.second(2).mock!.third(3) {4}}
41
+ subject.first(1).second(2).third(3).should == 4
42
+
43
+ mock(subject).first(1) {mock!.second(2).mock! {third(3) {4}}}
44
+ subject.first(1).second(2).third(3).should == 4
45
+
46
+ mock(subject).first(1).mock!.second(2).mock!.third(3) {4}
47
+ subject.first(1).second(2).third(3).should == 4
48
+ end
49
+
50
+ it 'allows chaining with proxy' do
51
+ find_return_value = Object.new
52
+ def find_return_value.child
53
+ :the_child
54
+ end
55
+ (class << subject; self; end).class_eval do
56
+ define_method(:find) do |id|
57
+ id == '1' ? find_return_value : raise(ArgumentError)
58
+ end
59
+ end
60
+
61
+ mock.proxy(subject).find('1').mock.proxy!.child
62
+ subject.find('1').child.should == :the_child
63
+ end
64
+
65
+ it 'allows branched chaining' do
66
+ mock(subject).first do
67
+ mock! do |expect|
68
+ expect.branch1 {mock!.branch11 {11}}
69
+ expect.branch2 {mock!.branch22 {22}}
70
+ end
71
+ end
72
+ o = subject.first
73
+ o.branch1.branch11.should == 11
74
+ o.branch2.branch22.should == 22
75
+ end
76
+
77
+ it 'allows chained ordering' do
78
+ mock(subject).to_s {"value 1"}.then.to_s {"value 2"}.twice.then.to_s {"value 3"}.once
79
+ subject.to_s.should == "value 1"
80
+ subject.to_s.should == "value 2"
81
+ subject.to_s.should == "value 2"
82
+ subject.to_s.should == "value 3"
83
+ lambda {subject.to_s}.should raise_error(RR::Errors::TimesCalledError)
84
+ end
85
+
86
+ it "mocks via block with argument" do
87
+ mock subject do |c|
88
+ c.to_s {"a value"}
89
+ c.to_sym {:crazy}
90
+ end
91
+ subject.to_s.should == "a value"
92
+ subject.to_sym.should == :crazy
93
+ end
94
+
95
+ it "mocks via block without argument" do
96
+ mock subject do
97
+ to_s {"a value"}
98
+ to_sym {:crazy}
99
+ end
100
+ subject.to_s.should == "a value"
101
+ subject.to_sym.should == :crazy
102
+ end
103
+
104
+ it "has wildcard matchers" do
105
+ mock(subject).foobar(
106
+ is_a(String),
107
+ anything,
108
+ numeric,
109
+ boolean,
110
+ duck_type(:to_s),
111
+ /abc/
112
+ ) {"value 1"}.twice
113
+ subject.foobar(
114
+ 'hello',
115
+ Object.new,
116
+ 99,
117
+ false,
118
+ "My String",
119
+ "Tabcola"
120
+ ).should == "value 1"
121
+ lambda do
122
+ subject.foobar(:failure)
123
+ end.should raise_error( RR::Errors::DoubleNotFoundError )
124
+ end
125
+
126
+ it "mocks methods without letters" do
127
+ mock(subject) == 55
128
+
129
+ subject == 55
130
+ lambda do
131
+ subject == 99
132
+ end.should raise_error(RR::Errors::DoubleNotFoundError)
133
+ end
134
+ end
135
+
136
+ describe "proxy" do
137
+ it "proxies via inline call" do
138
+ expected_to_s_value = subject.to_s
139
+ mock.proxy(subject).to_s
140
+ subject.to_s.should == expected_to_s_value
141
+ lambda {subject.to_s}.should raise_error
142
+ end
143
+
144
+ it "proxy allows ordering" do
145
+ def subject.to_s(arg)
146
+ "Original to_s with arg #{arg}"
147
+ end
148
+ mock.proxy(subject).to_s(:foo).ordered
149
+ mock.proxy(subject).to_s(:bar).twice.ordered
150
+
151
+ subject.to_s(:foo).should == "Original to_s with arg foo"
152
+ subject.to_s(:bar).should == "Original to_s with arg bar"
153
+ subject.to_s(:bar).should == "Original to_s with arg bar"
154
+ lambda {subject.to_s(:bar)}.should raise_error(RR::Errors::TimesCalledError)
155
+ end
156
+
157
+ it "proxy allows ordering" do
158
+ def subject.to_s(arg)
159
+ "Original to_s with arg #{arg}"
160
+ end
161
+ mock.proxy(subject).to_s(:foo).ordered
162
+ mock.proxy(subject).to_s(:bar).twice.ordered
163
+
164
+ subject.to_s(:foo).should == "Original to_s with arg foo"
165
+ subject.to_s(:bar).should == "Original to_s with arg bar"
166
+ subject.to_s(:bar).should == "Original to_s with arg bar"
167
+ lambda {subject.to_s(:bar)}.should raise_error(RR::Errors::TimesCalledError)
168
+ end
169
+
170
+ it "proxies via block with argument" do
171
+ def subject.foobar_1(*args)
172
+ :original_value_1
173
+ end
174
+
175
+ def subject.foobar_2
176
+ :original_value_2
177
+ end
178
+
179
+ mock.proxy subject do |c|
180
+ c.foobar_1(1)
181
+ c.foobar_2
182
+ end
183
+ subject.foobar_1(1).should == :original_value_1
184
+ lambda {subject.foobar_1(:blah)}.should raise_error
185
+
186
+ subject.foobar_2.should == :original_value_2
187
+ lambda {subject.foobar_2(:blah)}.should raise_error
188
+ end
189
+
190
+ it "proxies via block without argument" do
191
+ def subject.foobar_1(*args)
192
+ :original_value_1
193
+ end
194
+
195
+ def subject.foobar_2
196
+ :original_value_2
197
+ end
198
+
199
+ mock.proxy subject do
200
+ foobar_1(1)
201
+ foobar_2
202
+ end
203
+ subject.foobar_1(1).should == :original_value_1
204
+ lambda {subject.foobar_1(:blah)}.should raise_error
205
+
206
+ subject.foobar_2.should == :original_value_2
207
+ lambda {subject.foobar_2(:blah)}.should raise_error
208
+ end
209
+ end
210
+
211
+ describe "stub" do
212
+ it "stubs via inline call" do
213
+ stub(subject).to_s {"a value"}
214
+ subject.to_s.should == "a value"
215
+ end
216
+
217
+ it "allows ordering" do
218
+ stub(subject).to_s {"value 1"}.once.ordered
219
+ stub(subject).to_s {"value 2"}.once.ordered
220
+
221
+ subject.to_s.should == "value 1"
222
+ subject.to_s.should == "value 2"
223
+ end
224
+
225
+ it "stubs via block with argument" do
226
+ stub subject do |d|
227
+ d.to_s {"a value"}
228
+ d.to_sym {:crazy}
229
+ end
230
+ subject.to_s.should == "a value"
231
+ subject.to_sym.should == :crazy
232
+ end
233
+
234
+ it "stubs via block without argument" do
235
+ stub subject do
236
+ to_s {"a value"}
237
+ to_sym {:crazy}
238
+ end
239
+ subject.to_s.should == "a value"
240
+ subject.to_sym.should == :crazy
241
+ end
242
+
243
+ it "stubs instance_of" do
244
+ stub.instance_of(HighLevelSpec) do |o|
245
+ o.to_s {"High Level Spec"}
246
+ end
247
+ HighLevelSpec.new.to_s.should == "High Level Spec"
248
+ end
249
+
250
+ it "stubs methods without letters" do
251
+ stub(subject).__send__(:==) {:equality}
252
+ (subject == 55).should == :equality
253
+ end
254
+ end
255
+
256
+ describe "RR recorded_calls" do
257
+ it "should verify method calls after the fact" do
258
+ stub(subject).pig_rabbit
259
+ subject.pig_rabbit("bacon", "bunny meat")
260
+ #subject.should have_received.pig_rabitt("bacon", "bunny meat")
261
+ received(subject).pig_rabbit("bacon", "bunny meat").call
262
+ end
263
+
264
+ it "should verify method calls after the fact" do
265
+ stub(subject).pig_rabbit
266
+ lambda do
267
+ received(subject).pig_rabbit("bacon", "bunny meat").call
268
+ end.should raise_error(RR::Errors::SpyVerificationErrors::SpyVerificationError)
269
+ end
270
+ end
271
+
272
+ class StrongTestObject
273
+ def method_with_no_arguments
274
+ end
275
+
276
+ def method_with_one_argument(string)
277
+ end
278
+
279
+ def method_with_two_arguments(string, integer)
280
+ end
281
+
282
+ def method_with_three_arguments_including_varargs(string, integer, *args)
283
+ end
284
+
285
+ def method_with_varargs(*args)
286
+ end
287
+ end
288
+
289
+ describe "strong" do
290
+ context "when the method does not exist" do
291
+ it "raises an exception" do
292
+ lambda do
293
+ strong.stub(StrongTestObject.new).something
294
+ end.should raise_error(RR::Errors::SubjectDoesNotImplementMethodError)
295
+ end
296
+ end
297
+
298
+ context "when the method exists with no arguments" do
299
+ it "does not raise an exception" do
300
+ strong.stub(StrongTestObject.new).method_with_no_arguments
301
+ end
302
+ end
303
+
304
+ context "when the method has a different arity" do
305
+ it "raises an exception" do
306
+ lambda do
307
+ strong.stub(StrongTestObject.new).method_with_one_argument
308
+ end.should raise_error(RR::Errors::SubjectHasDifferentArityError)
309
+ end
310
+ end
311
+
312
+ context "when the method has accepts a variable number of arguments" do
313
+ it "does not raise an exception" do
314
+ strong.stub(StrongTestObject.new).method_with_varargs
315
+ end
316
+ end
317
+
318
+ context "when the method does not provide the required parameters before varargs" do
319
+ it "raises an exception" do
320
+ lambda do
321
+ strong.stub(StrongTestObject.new).method_with_three_arguments_including_varargs
322
+ end.should raise_error(RR::Errors::SubjectHasDifferentArityError)
323
+ end
324
+ end
325
+
326
+ context "when the minimum number of parameters are provided" do
327
+ it "does not raise an exception" do
328
+ strong.stub(StrongTestObject.new).method_with_three_arguments_including_varargs("one", 2)
329
+ end
330
+ end
331
+
332
+ context "when using instance_of and the method does not exist" do
333
+ it "raises an exception" do
334
+ lambda do
335
+ strong.stub.instance_of(StrongTestObject).something
336
+ StrongTestObject.new
337
+ end.should raise_error(RR::Errors::SubjectDoesNotImplementMethodError)
338
+ end
339
+ end
340
+
341
+ context "when using instance_of and the method does exist" do
342
+ it "does not raise an exception" do
343
+ strong.stub.instance_of(StrongTestObject).method_with_no_arguments
344
+ end
345
+ end
346
+ end
347
+
348
+ describe "spy" do
349
+ it "should record all method invocations" do
350
+ subject = Object.new
351
+ def subject.something
352
+ end
353
+
354
+ def subject.something_else
355
+ end
356
+
357
+ spy(subject)
358
+
359
+ subject.something
360
+ subject.something_else
361
+ subject.to_s
362
+
363
+ received(subject).something.call
364
+ received(subject).something_else.call
365
+ received(subject).to_s.call
366
+ end
367
+ end
368
+ end