jferris-rr 0.7.1.0.1239654108

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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