rr 0.10.5 → 0.10.6

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.
data/CHANGES CHANGED
@@ -1,3 +1,8 @@
1
+ - Added MIT license
2
+ - Fixed Bug - dont_allow doesn't work when it follows stub (http://github.com/btakita/rr/issues#issue/20)
3
+ - Fixed exception with DoubleInjections on proxy objects (http://github.com/btakita/rr/issues#issue/24)
4
+ - Fixed Bug - Can't stub attribute methods on a BelongsToAssociation (http://github.com/btakita/rr/issues#issue/24)
5
+
1
6
  0.10.5
2
7
  - Fixed issues with Ruby 1.9
3
8
  - Fixed stack overflow caused by double include in Test::Unit adapter [http://github.com/btakita/rr/issues#issue/16]. Identified by Dave Myron (http://github.com/contentfree)
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2010 Brian Takita
2
+
3
+ Permission is hereby granted, free of charge, to any person
4
+ obtaining a copy of this software and associated documentation
5
+ files (the "Software"), to deal in the Software without
6
+ restriction, including without limitation the rights to use,
7
+ copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ copies of the Software, and to permit persons to whom the
9
+ Software is furnished to do so, subject to the following
10
+ conditions:
11
+
12
+ The above copyright notice and this permission notice shall be
13
+ included in all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
17
+ OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19
+ HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20
+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22
+ OTHER DEALINGS IN THE SOFTWARE.
@@ -327,8 +327,8 @@ RR::WildcardMatchers for details.
327
327
  mock(object).method_name(anything).times(any_times) {return_value}
328
328
 
329
329
  == Special Thanks To
330
- With any development effort, there are countless people who have contributed
331
- to making it possible. We all are standing on the shoulders of giants.
330
+ With any development effort, there are countless people who have contributed to making it possible. We all are standing on the shoulders of giants.
331
+ If you have directly contributed to RR and I missed you in this list, please let me know and I will add you. Thanks!
332
332
  * Andreas Haller for patches
333
333
  * Aslak Hellesoy for Developing Rspec
334
334
  * Bryan Helmkamp for patches
@@ -347,9 +347,11 @@ to making it possible. We all are standing on the shoulders of giants.
347
347
  * Matthew O'Connor for patches and pairing with me
348
348
  * Michael Niessner for patches and pairing with me
349
349
  * Mike Mangino (from Elevated Rails) for patches and pairing with me
350
+ * Myron Marston for bug reports
350
351
  * Nick Kallen for documentation suggestions, bug reports, and patches
351
352
  * Nathan Sobo for various ideas and inspiration for cleaner and more expressive code
352
353
  * Parker Thompson for pairing with me
353
354
  * Phil Darnowsky for patches
354
355
  * Pivotal Labs for sponsoring RR development
355
356
  * Stephen Baker for Developing Rspec
357
+ * Tatsuya Ono for patches
@@ -1,5 +1,5 @@
1
1
  ---
2
- :patch: 5
3
2
  :build:
4
- :major: 0
5
3
  :minor: 10
4
+ :patch: 6
5
+ :major: 0
data/lib/rr.rb CHANGED
@@ -64,6 +64,7 @@ require "#{dir}/rr/wildcard_matchers/hash_including"
64
64
  require "#{dir}/rr/times_called_matchers/terminal"
65
65
  require "#{dir}/rr/times_called_matchers/non_terminal"
66
66
  require "#{dir}/rr/times_called_matchers/times_called_matcher"
67
+ require "#{dir}/rr/times_called_matchers/never_matcher"
67
68
  require "#{dir}/rr/times_called_matchers/any_times_matcher"
68
69
  require "#{dir}/rr/times_called_matchers/integer_matcher"
69
70
  require "#{dir}/rr/times_called_matchers/range_matcher"
@@ -97,7 +97,7 @@ module RR
97
97
  #
98
98
  # mock(subject).method_name.never
99
99
  def never
100
- @times_matcher = TimesCalledMatchers::IntegerMatcher.new(0)
100
+ @times_matcher = TimesCalledMatchers::NeverMatcher.new
101
101
  self
102
102
  end
103
103
 
@@ -21,7 +21,7 @@ module RR
21
21
  end
22
22
  end
23
23
 
24
- def register_self_at_double_definition_creator
24
+ def register_self_at_double_definition_creator(domain_name)
25
25
  end
26
26
  end
27
27
 
@@ -25,7 +25,6 @@ module RR
25
25
  def do_call
26
26
  definition.never
27
27
  permissive_argument
28
- reimplementation
29
28
  end
30
29
  end
31
30
  end
@@ -19,33 +19,24 @@ module RR
19
19
  if double.exact_match?(*args)
20
20
  matching_doubles << double
21
21
  if double.attempt?
22
- exact_double_is_terminal_or_non_terminal double
22
+ if double.terminal?
23
+ exact_terminal_doubles_to_attempt << double
24
+ else
25
+ exact_non_terminal_doubles_to_attempt << double
26
+ end
23
27
  end
24
28
  elsif double.wildcard_match?(*args)
25
29
  matching_doubles << double
26
30
  if double.attempt?
27
- wildcard_double_is_terminal_or_non_terminal double
31
+ if double.terminal?
32
+ wildcard_terminal_doubles_to_attempt << double
33
+ else
34
+ wildcard_non_terminal_doubles_to_attempt << double
35
+ end
28
36
  end
29
37
  end
30
38
  end
31
39
  self
32
40
  end
33
-
34
- protected
35
- def exact_double_is_terminal_or_non_terminal(double)
36
- if double.terminal?
37
- exact_terminal_doubles_to_attempt << double
38
- else
39
- exact_non_terminal_doubles_to_attempt << double
40
- end
41
- end
42
-
43
- def wildcard_double_is_terminal_or_non_terminal(double)
44
- if double.terminal?
45
- wildcard_terminal_doubles_to_attempt << double
46
- else
47
- wildcard_non_terminal_doubles_to_attempt << double
48
- end
49
- end
50
41
  end
51
42
  end
@@ -28,7 +28,11 @@ module RR
28
28
  def bind
29
29
  if subject_respond_to_method?(method_name)
30
30
  if subject_has_method_defined?(method_name)
31
- bind_method_with_alias
31
+ if subject_is_proxy_for_method?(method_name)
32
+ bind_method
33
+ else
34
+ bind_method_with_alias
35
+ end
32
36
  else
33
37
  space.method_missing_injection(subject)
34
38
  space.singleton_method_added_injection(subject)
@@ -95,6 +99,11 @@ module RR
95
99
  end
96
100
 
97
101
  protected
102
+ def subject_is_proxy_for_method?(method_name)
103
+ method_owner = @subject.method(method_name).owner
104
+ !(subject_class.object_id == method_owner.object_id || subject_class.ancestors.include?(method_owner))
105
+ end
106
+
98
107
  def deferred_bind_method
99
108
  unless subject_has_method_defined?(original_method_alias_name)
100
109
  bind_method_with_alias
@@ -108,13 +117,13 @@ module RR
108
117
  end
109
118
 
110
119
  def bind_method
111
- returns_method = <<-METHOD
120
+ subject = @subject.is_a?(Class) && !@subject.name.empty? ? @subject.name : "self"
121
+ subject_class.class_eval(<<-METHOD, __FILE__, __LINE__ + 1)
112
122
  def #{@method_name}(*args, &block)
113
123
  arguments = MethodArguments.new(args, block)
114
- RR::Space.double_injection(self, :#{@method_name}).dispatch_method(arguments.arguments, arguments.block)
124
+ RR::Space.double_injection(#{subject}, :#{@method_name}).dispatch_method(arguments.arguments, arguments.block)
115
125
  end
116
126
  METHOD
117
- subject_class.class_eval(returns_method, __FILE__, __LINE__ - 5)
118
127
  end
119
128
  end
120
129
  end
@@ -12,11 +12,12 @@ module RR
12
12
  if double
13
13
  double.method_call(args)
14
14
  call_yields
15
- return_value = extract_subject_from_return_value(call_implementation)
15
+ return_value_1 = call_implementation
16
+ return_value_2 = extract_subject_from_return_value(return_value_1)
16
17
  if after_call_proc
17
- extract_subject_from_return_value(after_call_proc.call(return_value))
18
+ extract_subject_from_return_value(after_call_proc.call(return_value_2))
18
19
  else
19
- return_value
20
+ return_value_2
20
21
  end
21
22
  else
22
23
  double_not_found_error
@@ -0,0 +1,23 @@
1
+ module RR
2
+ module TimesCalledMatchers #:nodoc:
3
+ class NeverMatcher < TimesCalledMatcher
4
+ include Terminal
5
+
6
+ def initialize
7
+ super 0
8
+ end
9
+
10
+ def possible_match?(times_called)
11
+ true
12
+ end
13
+
14
+ def matches?(times_called)
15
+ true
16
+ end
17
+
18
+ def attempt?(times_called)
19
+ raise RR::Errors::TimesCalledError, error_message(1)
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,14 @@
1
+ require File.expand_path("#{File.dirname(__FILE__)}/../../spec_helper")
2
+
3
+ describe "dont_allow called after stub" do
4
+ context "when the subject method is called" do
5
+ it "raises a TimesCalledError" do
6
+ subject = Object.new
7
+ stub(subject).foobar
8
+ dont_allow(subject).foobar
9
+ lambda do
10
+ subject.foobar
11
+ end.should raise_error(RR::Errors::TimesCalledError)
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,183 @@
1
+ require File.expand_path("#{File.dirname(__FILE__)}/../../spec_helper")
2
+
3
+ describe "mock" do
4
+ attr_reader :subject
5
+ before(:each) do
6
+ @subject = Object.new
7
+ extend RR::Adapters::RRMethods
8
+ end
9
+
10
+ after(:each) do
11
+ RR.reset
12
+ end
13
+
14
+ it "mocks via inline call" do
15
+ mock(subject).to_s {"a value"}
16
+ subject.to_s.should == "a value"
17
+ lambda {subject.to_s}.should raise_error(RR::Errors::TimesCalledError)
18
+ end
19
+
20
+ describe ".once.ordered" do
21
+ it "returns the values in the ordered called" do
22
+ mock(subject).to_s {"value 1"}.ordered
23
+ mock(subject).to_s {"value 2"}.twice
24
+ subject.to_s.should == "value 1"
25
+ subject.to_s.should == "value 2"
26
+ subject.to_s.should == "value 2"
27
+ lambda {subject.to_s}.should raise_error(RR::Errors::TimesCalledError)
28
+ end
29
+ end
30
+
31
+ context "when the subject is a proxy for the object with the defined method" do
32
+ it "stubs the method on the proxy object" do
33
+ proxy_target = Class.new {def foobar; :original_foobar; end}.new
34
+ proxy = Class.new do
35
+ def initialize(target)
36
+ @target = target
37
+ end
38
+
39
+ instance_methods.each do |m|
40
+ unless m =~ /^_/ || m.to_s == 'object_id' || m.to_s == 'method_missing'
41
+ alias_method "__blank_slated_#{m}", m
42
+ undef_method m
43
+ end
44
+ end
45
+
46
+ def method_missing(method_name, *args, &block)
47
+ @target.send(method_name, *args, &block)
48
+ end
49
+ end.new(proxy_target)
50
+ proxy.methods.should =~ proxy_target.methods
51
+
52
+ mock(proxy).foobar {:new_foobar}
53
+ proxy.foobar.should == :new_foobar
54
+ end
55
+ end
56
+
57
+ it 'allows terse chaining' do
58
+ mock(subject).first(1) {mock(Object.new).second(2) {mock(Object.new).third(3) {4}}}
59
+ subject.first(1).second(2).third(3).should == 4
60
+
61
+ mock(subject).first(1) {mock!.second(2) {mock!.third(3) {4}}}
62
+ subject.first(1).second(2).third(3).should == 4
63
+
64
+ mock(subject).first(1) {mock!.second(2).mock!.third(3) {4}}
65
+ subject.first(1).second(2).third(3).should == 4
66
+
67
+ mock(subject).first(1) {mock!.second(2).mock! {third(3) {4}}}
68
+ subject.first(1).second(2).third(3).should == 4
69
+
70
+ mock(subject).first(1).mock!.second(2).mock!.third(3) {4}
71
+ subject.first(1).second(2).third(3).should == 4
72
+ end
73
+
74
+ it 'allows chaining with proxy' do
75
+ find_return_value = Object.new
76
+ def find_return_value.child
77
+ :the_child
78
+ end
79
+ (class << subject; self; end).class_eval do
80
+ define_method(:find) do |id|
81
+ id == '1' ? find_return_value : raise(ArgumentError)
82
+ end
83
+ end
84
+
85
+ mock.proxy(subject).find('1').mock.proxy!.child
86
+ subject.find('1').child.should == :the_child
87
+ end
88
+
89
+ it 'allows branched chaining' do
90
+ mock(subject).first do
91
+ mock! do |expect|
92
+ expect.branch1 {mock!.branch11 {11}}
93
+ expect.branch2 {mock!.branch22 {22}}
94
+ end
95
+ end
96
+ o = subject.first
97
+ o.branch1.branch11.should == 11
98
+ o.branch2.branch22.should == 22
99
+ end
100
+
101
+ it 'allows chained ordering' do
102
+ mock(subject).to_s {"value 1"}.then.to_s {"value 2"}.twice.then.to_s {"value 3"}.once
103
+ subject.to_s.should == "value 1"
104
+ subject.to_s.should == "value 2"
105
+ subject.to_s.should == "value 2"
106
+ subject.to_s.should == "value 3"
107
+ lambda {subject.to_s}.should raise_error(RR::Errors::TimesCalledError)
108
+ end
109
+
110
+ it "mocks via block with argument" do
111
+ mock subject do |c|
112
+ c.to_s {"a value"}
113
+ c.to_sym {:crazy}
114
+ end
115
+ subject.to_s.should == "a value"
116
+ subject.to_sym.should == :crazy
117
+ end
118
+
119
+ it "mocks via block without argument" do
120
+ mock subject do
121
+ to_s {"a value"}
122
+ to_sym {:crazy}
123
+ end
124
+ subject.to_s.should == "a value"
125
+ subject.to_sym.should == :crazy
126
+ end
127
+
128
+ it "has wildcard matchers" do
129
+ mock(subject).foobar(
130
+ is_a(String),
131
+ anything,
132
+ numeric,
133
+ boolean,
134
+ duck_type(:to_s),
135
+ /abc/
136
+ ) {"value 1"}.twice
137
+ subject.foobar(
138
+ 'hello',
139
+ Object.new,
140
+ 99,
141
+ false,
142
+ "My String",
143
+ "Tabcola"
144
+ ).should == "value 1"
145
+ lambda do
146
+ subject.foobar(:failure)
147
+ end.should raise_error( RR::Errors::DoubleNotFoundError )
148
+ end
149
+
150
+ it "mocks methods without letters" do
151
+ mock(subject) == 55
152
+
153
+ subject == 55
154
+ lambda do
155
+ subject == 99
156
+ end.should raise_error(RR::Errors::DoubleNotFoundError)
157
+ end
158
+
159
+ describe "on class method" do
160
+ class SampleClass1
161
+ def self.hello; "hello!"; end
162
+ end
163
+
164
+ class SampleClass2 < SampleClass1; end
165
+
166
+ it "can mock" do
167
+ mock(SampleClass1).hello { "hola!" }
168
+
169
+ SampleClass1.hello.should == "hola!"
170
+ end
171
+
172
+ it "should not break when it is mocked on subclass" do
173
+ mock(SampleClass1).hello { "hi!" }
174
+
175
+ SampleClass2.hello.should == "hi!"
176
+ end
177
+
178
+ it "should not get affected from a previous example" do
179
+ SampleClass2.hello.should == "hello!"
180
+ end
181
+
182
+ end
183
+ end
@@ -0,0 +1,86 @@
1
+ require File.expand_path("#{File.dirname(__FILE__)}/../../spec_helper")
2
+
3
+ describe "proxy" do
4
+ attr_reader :subject
5
+ before(:each) do
6
+ @subject = Object.new
7
+ extend RR::Adapters::RRMethods
8
+ end
9
+
10
+ after(:each) do
11
+ RR.reset
12
+ end
13
+
14
+ it "proxies via inline call" do
15
+ expected_to_s_value = subject.to_s
16
+ mock.proxy(subject).to_s
17
+ subject.to_s.should == expected_to_s_value
18
+ lambda {subject.to_s}.should raise_error
19
+ end
20
+
21
+ it "proxy allows ordering" do
22
+ def subject.to_s(arg)
23
+ "Original to_s with arg #{arg}"
24
+ end
25
+ mock.proxy(subject).to_s(:foo).ordered
26
+ mock.proxy(subject).to_s(:bar).twice.ordered
27
+
28
+ subject.to_s(:foo).should == "Original to_s with arg foo"
29
+ subject.to_s(:bar).should == "Original to_s with arg bar"
30
+ subject.to_s(:bar).should == "Original to_s with arg bar"
31
+ lambda {subject.to_s(:bar)}.should raise_error(RR::Errors::TimesCalledError)
32
+ end
33
+
34
+ it "proxy allows ordering" do
35
+ def subject.to_s(arg)
36
+ "Original to_s with arg #{arg}"
37
+ end
38
+ mock.proxy(subject).to_s(:foo).ordered
39
+ mock.proxy(subject).to_s(:bar).twice.ordered
40
+
41
+ subject.to_s(:foo).should == "Original to_s with arg foo"
42
+ subject.to_s(:bar).should == "Original to_s with arg bar"
43
+ subject.to_s(:bar).should == "Original to_s with arg bar"
44
+ lambda {subject.to_s(:bar)}.should raise_error(RR::Errors::TimesCalledError)
45
+ end
46
+
47
+ it "proxies via block with argument" do
48
+ def subject.foobar_1(*args)
49
+ :original_value_1
50
+ end
51
+
52
+ def subject.foobar_2
53
+ :original_value_2
54
+ end
55
+
56
+ mock.proxy subject do |c|
57
+ c.foobar_1(1)
58
+ c.foobar_2
59
+ end
60
+ subject.foobar_1(1).should == :original_value_1
61
+ lambda {subject.foobar_1(:blah)}.should raise_error
62
+
63
+ subject.foobar_2.should == :original_value_2
64
+ lambda {subject.foobar_2(:blah)}.should raise_error
65
+ end
66
+
67
+ it "proxies via block without argument" do
68
+ def subject.foobar_1(*args)
69
+ :original_value_1
70
+ end
71
+
72
+ def subject.foobar_2
73
+ :original_value_2
74
+ end
75
+
76
+ mock.proxy subject do
77
+ foobar_1(1)
78
+ foobar_2
79
+ end
80
+ subject.foobar_1(1).should == :original_value_1
81
+ lambda {subject.foobar_1(:blah)}.should raise_error
82
+
83
+ subject.foobar_2.should == :original_value_2
84
+ lambda {subject.foobar_2(:blah)}.should raise_error
85
+ end
86
+ end
@@ -0,0 +1,48 @@
1
+ require File.expand_path("#{File.dirname(__FILE__)}/../../spec_helper")
2
+
3
+ describe "spy" do
4
+ attr_reader :subject
5
+ before(:each) do
6
+ @subject = Object.new
7
+ extend RR::Adapters::RRMethods
8
+ end
9
+
10
+ after(:each) do
11
+ RR.reset
12
+ end
13
+
14
+ it "should record all method invocations" do
15
+ subject = Object.new
16
+ def subject.something
17
+ end
18
+
19
+ def subject.something_else
20
+ end
21
+
22
+ spy(subject)
23
+
24
+ subject.something
25
+ subject.something_else
26
+ subject.to_s
27
+
28
+ received(subject).something.call
29
+ received(subject).something_else.call
30
+ received(subject).to_s.call
31
+ end
32
+
33
+ describe "RR recorded_calls" do
34
+ it "should verify method calls after the fact" do
35
+ stub(subject).pig_rabbit
36
+ subject.pig_rabbit("bacon", "bunny meat")
37
+ #subject.should have_received.pig_rabitt("bacon", "bunny meat")
38
+ received(subject).pig_rabbit("bacon", "bunny meat").call
39
+ end
40
+
41
+ it "should verify method calls after the fact" do
42
+ stub(subject).pig_rabbit
43
+ lambda do
44
+ received(subject).pig_rabbit("bacon", "bunny meat").call
45
+ end.should raise_error(RR::Errors::SpyVerificationErrors::SpyVerificationError)
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,87 @@
1
+ require File.expand_path("#{File.dirname(__FILE__)}/../../spec_helper")
2
+
3
+ class StrongSpecFixture
4
+ def method_with_no_arguments
5
+ end
6
+
7
+ def method_with_one_argument(string)
8
+ end
9
+
10
+ def method_with_two_arguments(string, integer)
11
+ end
12
+
13
+ def method_with_three_arguments_including_varargs(string, integer, *args)
14
+ end
15
+
16
+ def method_with_varargs(*args)
17
+ end
18
+ end
19
+
20
+ describe "strong" do
21
+ attr_reader :subject
22
+ before(:each) do
23
+ @subject = Object.new
24
+ extend RR::Adapters::RRMethods
25
+ end
26
+
27
+ after(:each) do
28
+ RR.reset
29
+ end
30
+
31
+ context "when the method does not exist" do
32
+ it "raises an exception" do
33
+ lambda do
34
+ strong.stub(StrongSpecFixture.new).something
35
+ end.should raise_error(RR::Errors::SubjectDoesNotImplementMethodError)
36
+ end
37
+ end
38
+
39
+ context "when the method exists with no arguments" do
40
+ it "does not raise an exception" do
41
+ strong.stub(StrongSpecFixture.new).method_with_no_arguments
42
+ end
43
+ end
44
+
45
+ context "when the method has a different arity" do
46
+ it "raises an exception" do
47
+ lambda do
48
+ strong.stub(StrongSpecFixture.new).method_with_one_argument
49
+ end.should raise_error(RR::Errors::SubjectHasDifferentArityError)
50
+ end
51
+ end
52
+
53
+ context "when the method has accepts a variable number of arguments" do
54
+ it "does not raise an exception" do
55
+ strong.stub(StrongSpecFixture.new).method_with_varargs
56
+ end
57
+ end
58
+
59
+ context "when the method does not provide the required parameters before varargs" do
60
+ it "raises an exception" do
61
+ lambda do
62
+ strong.stub(StrongSpecFixture.new).method_with_three_arguments_including_varargs
63
+ end.should raise_error(RR::Errors::SubjectHasDifferentArityError)
64
+ end
65
+ end
66
+
67
+ context "when the minimum number of parameters are provided" do
68
+ it "does not raise an exception" do
69
+ strong.stub(StrongSpecFixture.new).method_with_three_arguments_including_varargs("one", 2)
70
+ end
71
+ end
72
+
73
+ context "when using instance_of and the method does not exist" do
74
+ it "raises an exception" do
75
+ lambda do
76
+ strong.stub.instance_of(StrongSpecFixture).something
77
+ StrongSpecFixture.new
78
+ end.should raise_error(RR::Errors::SubjectDoesNotImplementMethodError)
79
+ end
80
+ end
81
+
82
+ context "when using instance_of and the method does exist" do
83
+ it "does not raise an exception" do
84
+ strong.stub.instance_of(StrongSpecFixture).method_with_no_arguments
85
+ end
86
+ end
87
+ end
@@ -0,0 +1,126 @@
1
+ require File.expand_path("#{File.dirname(__FILE__)}/../../spec_helper")
2
+
3
+ class StubSpecFixture
4
+ attr_reader :initialize_arguments
5
+
6
+ def initialize(*args)
7
+ @initialize_arguments = args
8
+ yield if block_given?
9
+ method_run_in_initialize
10
+ end
11
+
12
+ def method_run_in_initialize
13
+
14
+ end
15
+ end
16
+
17
+ describe "stub" do
18
+ attr_reader :subject
19
+ before(:each) do
20
+ @subject = Object.new
21
+ extend RR::Adapters::RRMethods
22
+ end
23
+
24
+ after(:each) do
25
+ RR.reset
26
+ end
27
+
28
+ it "stubs via inline call" do
29
+ stub(subject).to_s {"a value"}
30
+ subject.to_s.should == "a value"
31
+ end
32
+
33
+ describe ".once.ordered" do
34
+ it "returns the values in the ordered called" do
35
+ stub(subject).to_s {"value 1"}.once.ordered
36
+ stub(subject).to_s {"value 2"}.once.ordered
37
+
38
+ subject.to_s.should == "value 1"
39
+ subject.to_s.should == "value 2"
40
+ end
41
+ end
42
+
43
+ context "when the subject is a proxy for the object with the defined method" do
44
+ it "stubs the method on the proxy object" do
45
+ proxy_target = Class.new {def foobar; :original_foobar; end}.new
46
+ proxy = Class.new do
47
+ def initialize(target)
48
+ @target = target
49
+ end
50
+
51
+ instance_methods.each do |m|
52
+ unless m =~ /^_/ || m.to_s == 'object_id' || m.to_s == 'method_missing'
53
+ alias_method "__blank_slated_#{m}", m
54
+ undef_method m
55
+ end
56
+ end
57
+
58
+ def method_missing(method_name, *args, &block)
59
+ @target.send(method_name, *args, &block)
60
+ end
61
+ end.new(proxy_target)
62
+ proxy.methods.should =~ proxy_target.methods
63
+
64
+ stub(proxy).foobar {:new_foobar}
65
+ proxy.foobar.should == :new_foobar
66
+ end
67
+ end
68
+
69
+ it "stubs via block with argument" do
70
+ stub subject do |d|
71
+ d.to_s {"a value"}
72
+ d.to_sym {:crazy}
73
+ end
74
+ subject.to_s.should == "a value"
75
+ subject.to_sym.should == :crazy
76
+ end
77
+
78
+ it "stubs via block without argument" do
79
+ stub subject do
80
+ to_s {"a value"}
81
+ to_sym {:crazy}
82
+ end
83
+ subject.to_s.should == "a value"
84
+ subject.to_sym.should == :crazy
85
+ end
86
+
87
+ it "stubs instance_of" do
88
+ stub.instance_of(StubSpecFixture) do |o|
89
+ o.to_s {"High Level Spec"}
90
+ end
91
+ StubSpecFixture.new.to_s.should == "High Level Spec"
92
+ end
93
+
94
+ it "stubs methods without letters" do
95
+ stub(subject).__send__(:==) {:equality}
96
+ (subject == 55).should == :equality
97
+ end
98
+
99
+ it "stubs methods invoked in #initialize while passing along the #initialize arg" do
100
+ method_run_in_initialize_stubbed = false
101
+ stub.instance_of(StubSpecFixture) do |o|
102
+ o.method_run_in_initialize {method_run_in_initialize_stubbed = true}
103
+ end
104
+ StubSpecFixture.new
105
+ method_run_in_initialize_stubbed.should be_true
106
+ end
107
+
108
+ it "passed the arguments and block passed to #initialize" do
109
+ block_called = false
110
+ stub.instance_of(StubSpecFixture) do |o|
111
+ o.method_run_in_initialize
112
+ end
113
+ instance = StubSpecFixture.new(1, 2) {block_called = true}
114
+ instance.initialize_arguments.should == [1, 2]
115
+ block_called.should be_true
116
+ end
117
+
118
+ context "mock then stub" do
119
+ it "stubs any calls not matching the mock" do
120
+ mock(subject).foobar(3) {:baz3}
121
+ stub(subject).foobar {:baz}
122
+ subject.foobar(3).should == :baz3
123
+ subject.foobar(4).should == :baz
124
+ end
125
+ end
126
+ end
@@ -81,7 +81,7 @@ module RR
81
81
  context "when passed a method_name argument_expectation" do
82
82
  it "creates a mock Double for method" do
83
83
  double_definition = dont_allow(subject, :foobar)
84
- double_definition.times_matcher.should == TimesCalledMatchers::IntegerMatcher.new(0)
84
+ double_definition.times_matcher.should == TimesCalledMatchers::NeverMatcher.new
85
85
  double_definition.argument_expectation.class.should == RR::Expectations::AnyArgumentExpectation
86
86
 
87
87
  lambda do
@@ -111,7 +111,7 @@ module RR
111
111
  context "when passed a subject and a method_name argument_expectation" do
112
112
  it "creates a mock Double for method" do
113
113
  double_definition = creator.dont_allow(subject, :foobar)
114
- double_definition.times_matcher.should == TimesCalledMatchers::IntegerMatcher.new(0)
114
+ double_definition.times_matcher.should == TimesCalledMatchers::NeverMatcher.new
115
115
  double_definition.argument_expectation.class.should == RR::Expectations::AnyArgumentExpectation
116
116
 
117
117
  lambda do
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rr
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.10.5
4
+ version: 0.10.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Brian Takita
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-12-20 00:00:00 -08:00
12
+ date: 2010-02-15 00:00:00 -08:00
13
13
  default_executable:
14
14
  dependencies: []
15
15
 
@@ -24,6 +24,7 @@ extra_rdoc_files:
24
24
  - README.rdoc
25
25
  files:
26
26
  - CHANGES
27
+ - LICENSE
27
28
  - README.rdoc
28
29
  - Rakefile
29
30
  - VERSION.yml
@@ -80,6 +81,7 @@ files:
80
81
  - lib/rr/times_called_matchers/at_least_matcher.rb
81
82
  - lib/rr/times_called_matchers/at_most_matcher.rb
82
83
  - lib/rr/times_called_matchers/integer_matcher.rb
84
+ - lib/rr/times_called_matchers/never_matcher.rb
83
85
  - lib/rr/times_called_matchers/non_terminal.rb
84
86
  - lib/rr/times_called_matchers/proc_matcher.rb
85
87
  - lib/rr/times_called_matchers/range_matcher.rb
@@ -96,9 +98,14 @@ files:
96
98
  - lib/rr/wildcard_matchers/regexp.rb
97
99
  - lib/rr/wildcard_matchers/satisfy.rb
98
100
  - ruby_19_spec.rb
101
+ - spec/api/dont_allow/dont_allow_after_stub_spec.rb
102
+ - spec/api/mock/mock_spec.rb
103
+ - spec/api/proxy/proxy_spec.rb
104
+ - spec/api/spy/spy_spec.rb
105
+ - spec/api/strong/strong_spec.rb
106
+ - spec/api/stub/stub_spec.rb
99
107
  - spec/core_spec_suite.rb
100
108
  - spec/environment_fixture_setup.rb
101
- - spec/high_level_spec.rb
102
109
  - spec/proc_from_block_spec.rb
103
110
  - spec/rr/adapters/rr_methods_argument_matcher_spec.rb
104
111
  - spec/rr/adapters/rr_methods_creator_spec.rb
@@ -192,6 +199,5 @@ specification_version: 3
192
199
  summary: RR (Double Ruby) is a double framework that features a rich selection of double techniques and a terse syntax. http://xunitpatterns.com/Test%20Double.html
193
200
  test_files:
194
201
  - spec/spy_verification_spec.rb
195
- - spec/high_level_spec.rb
196
202
  - spec/rr_spec.rb
197
203
  - spec/proc_from_block_spec.rb
@@ -1,398 +0,0 @@
1
- require File.expand_path("#{File.dirname(__FILE__)}/spec_helper")
2
-
3
- class HighLevelSpec
4
- attr_reader :initialize_arguments
5
-
6
- def initialize(*args)
7
- @initialize_arguments = args
8
- yield if block_given?
9
- method_run_in_initialize
10
- end
11
-
12
- def method_run_in_initialize
13
-
14
- end
15
- end
16
-
17
- describe "RR" do
18
- attr_reader :subject
19
- before(:each) do
20
- @subject = Object.new
21
- extend RR::Adapters::RRMethods
22
- end
23
-
24
- after(:each) do
25
- RR.reset
26
- end
27
-
28
- describe "mock" do
29
- it "mocks via inline call" do
30
- mock(subject).to_s {"a value"}
31
- subject.to_s.should == "a value"
32
- lambda {subject.to_s}.should raise_error(RR::Errors::TimesCalledError)
33
- end
34
-
35
- it "allows ordering" do
36
- mock(subject).to_s {"value 1"}.ordered
37
- mock(subject).to_s {"value 2"}.twice
38
- subject.to_s.should == "value 1"
39
- subject.to_s.should == "value 2"
40
- subject.to_s.should == "value 2"
41
- lambda {subject.to_s}.should raise_error(RR::Errors::TimesCalledError)
42
- end
43
-
44
- it 'allows terse chaining' do
45
- mock(subject).first(1) {mock(Object.new).second(2) {mock(Object.new).third(3) {4}}}
46
- subject.first(1).second(2).third(3).should == 4
47
-
48
- mock(subject).first(1) {mock!.second(2) {mock!.third(3) {4}}}
49
- subject.first(1).second(2).third(3).should == 4
50
-
51
- mock(subject).first(1) {mock!.second(2).mock!.third(3) {4}}
52
- subject.first(1).second(2).third(3).should == 4
53
-
54
- mock(subject).first(1) {mock!.second(2).mock! {third(3) {4}}}
55
- subject.first(1).second(2).third(3).should == 4
56
-
57
- mock(subject).first(1).mock!.second(2).mock!.third(3) {4}
58
- subject.first(1).second(2).third(3).should == 4
59
- end
60
-
61
- it 'allows chaining with proxy' do
62
- find_return_value = Object.new
63
- def find_return_value.child
64
- :the_child
65
- end
66
- (class << subject; self; end).class_eval do
67
- define_method(:find) do |id|
68
- id == '1' ? find_return_value : raise(ArgumentError)
69
- end
70
- end
71
-
72
- mock.proxy(subject).find('1').mock.proxy!.child
73
- subject.find('1').child.should == :the_child
74
- end
75
-
76
- it 'allows branched chaining' do
77
- mock(subject).first do
78
- mock! do |expect|
79
- expect.branch1 {mock!.branch11 {11}}
80
- expect.branch2 {mock!.branch22 {22}}
81
- end
82
- end
83
- o = subject.first
84
- o.branch1.branch11.should == 11
85
- o.branch2.branch22.should == 22
86
- end
87
-
88
- it 'allows chained ordering' do
89
- mock(subject).to_s {"value 1"}.then.to_s {"value 2"}.twice.then.to_s {"value 3"}.once
90
- subject.to_s.should == "value 1"
91
- subject.to_s.should == "value 2"
92
- subject.to_s.should == "value 2"
93
- subject.to_s.should == "value 3"
94
- lambda {subject.to_s}.should raise_error(RR::Errors::TimesCalledError)
95
- end
96
-
97
- it "mocks via block with argument" do
98
- mock subject do |c|
99
- c.to_s {"a value"}
100
- c.to_sym {:crazy}
101
- end
102
- subject.to_s.should == "a value"
103
- subject.to_sym.should == :crazy
104
- end
105
-
106
- it "mocks via block without argument" do
107
- mock subject do
108
- to_s {"a value"}
109
- to_sym {:crazy}
110
- end
111
- subject.to_s.should == "a value"
112
- subject.to_sym.should == :crazy
113
- end
114
-
115
- it "has wildcard matchers" do
116
- mock(subject).foobar(
117
- is_a(String),
118
- anything,
119
- numeric,
120
- boolean,
121
- duck_type(:to_s),
122
- /abc/
123
- ) {"value 1"}.twice
124
- subject.foobar(
125
- 'hello',
126
- Object.new,
127
- 99,
128
- false,
129
- "My String",
130
- "Tabcola"
131
- ).should == "value 1"
132
- lambda do
133
- subject.foobar(:failure)
134
- end.should raise_error( RR::Errors::DoubleNotFoundError )
135
- end
136
-
137
- it "mocks methods without letters" do
138
- mock(subject) == 55
139
-
140
- subject == 55
141
- lambda do
142
- subject == 99
143
- end.should raise_error(RR::Errors::DoubleNotFoundError)
144
- end
145
- end
146
-
147
- describe "proxy" do
148
- it "proxies via inline call" do
149
- expected_to_s_value = subject.to_s
150
- mock.proxy(subject).to_s
151
- subject.to_s.should == expected_to_s_value
152
- lambda {subject.to_s}.should raise_error
153
- end
154
-
155
- it "proxy allows ordering" do
156
- def subject.to_s(arg)
157
- "Original to_s with arg #{arg}"
158
- end
159
- mock.proxy(subject).to_s(:foo).ordered
160
- mock.proxy(subject).to_s(:bar).twice.ordered
161
-
162
- subject.to_s(:foo).should == "Original to_s with arg foo"
163
- subject.to_s(:bar).should == "Original to_s with arg bar"
164
- subject.to_s(:bar).should == "Original to_s with arg bar"
165
- lambda {subject.to_s(:bar)}.should raise_error(RR::Errors::TimesCalledError)
166
- end
167
-
168
- it "proxy allows ordering" do
169
- def subject.to_s(arg)
170
- "Original to_s with arg #{arg}"
171
- end
172
- mock.proxy(subject).to_s(:foo).ordered
173
- mock.proxy(subject).to_s(:bar).twice.ordered
174
-
175
- subject.to_s(:foo).should == "Original to_s with arg foo"
176
- subject.to_s(:bar).should == "Original to_s with arg bar"
177
- subject.to_s(:bar).should == "Original to_s with arg bar"
178
- lambda {subject.to_s(:bar)}.should raise_error(RR::Errors::TimesCalledError)
179
- end
180
-
181
- it "proxies via block with argument" do
182
- def subject.foobar_1(*args)
183
- :original_value_1
184
- end
185
-
186
- def subject.foobar_2
187
- :original_value_2
188
- end
189
-
190
- mock.proxy subject do |c|
191
- c.foobar_1(1)
192
- c.foobar_2
193
- end
194
- subject.foobar_1(1).should == :original_value_1
195
- lambda {subject.foobar_1(:blah)}.should raise_error
196
-
197
- subject.foobar_2.should == :original_value_2
198
- lambda {subject.foobar_2(:blah)}.should raise_error
199
- end
200
-
201
- it "proxies via block without argument" do
202
- def subject.foobar_1(*args)
203
- :original_value_1
204
- end
205
-
206
- def subject.foobar_2
207
- :original_value_2
208
- end
209
-
210
- mock.proxy subject do
211
- foobar_1(1)
212
- foobar_2
213
- end
214
- subject.foobar_1(1).should == :original_value_1
215
- lambda {subject.foobar_1(:blah)}.should raise_error
216
-
217
- subject.foobar_2.should == :original_value_2
218
- lambda {subject.foobar_2(:blah)}.should raise_error
219
- end
220
- end
221
-
222
- describe "stub" do
223
- it "stubs via inline call" do
224
- stub(subject).to_s {"a value"}
225
- subject.to_s.should == "a value"
226
- end
227
-
228
- it "allows ordering" do
229
- stub(subject).to_s {"value 1"}.once.ordered
230
- stub(subject).to_s {"value 2"}.once.ordered
231
-
232
- subject.to_s.should == "value 1"
233
- subject.to_s.should == "value 2"
234
- end
235
-
236
- it "stubs via block with argument" do
237
- stub subject do |d|
238
- d.to_s {"a value"}
239
- d.to_sym {:crazy}
240
- end
241
- subject.to_s.should == "a value"
242
- subject.to_sym.should == :crazy
243
- end
244
-
245
- it "stubs via block without argument" do
246
- stub subject do
247
- to_s {"a value"}
248
- to_sym {:crazy}
249
- end
250
- subject.to_s.should == "a value"
251
- subject.to_sym.should == :crazy
252
- end
253
-
254
- it "stubs instance_of" do
255
- stub.instance_of(HighLevelSpec) do |o|
256
- o.to_s {"High Level Spec"}
257
- end
258
- HighLevelSpec.new.to_s.should == "High Level Spec"
259
- end
260
-
261
- it "stubs methods without letters" do
262
- stub(subject).__send__(:==) {:equality}
263
- (subject == 55).should == :equality
264
- end
265
-
266
- it "stubs methods invoked in #initialize while passing along the #initialize arg" do
267
- method_run_in_initialize_stubbed = false
268
- stub.instance_of(HighLevelSpec) do |o|
269
- o.method_run_in_initialize {method_run_in_initialize_stubbed = true}
270
- end
271
- HighLevelSpec.new
272
- method_run_in_initialize_stubbed.should be_true
273
- end
274
-
275
- it "passed the arguments and block passed to #initialize" do
276
- block_called = false
277
- stub.instance_of(HighLevelSpec) do |o|
278
- o.method_run_in_initialize
279
- end
280
- instance = HighLevelSpec.new(1, 2) {block_called = true}
281
- instance.initialize_arguments.should == [1, 2]
282
- block_called.should be_true
283
- end
284
- end
285
-
286
- describe "RR recorded_calls" do
287
- it "should verify method calls after the fact" do
288
- stub(subject).pig_rabbit
289
- subject.pig_rabbit("bacon", "bunny meat")
290
- #subject.should have_received.pig_rabitt("bacon", "bunny meat")
291
- received(subject).pig_rabbit("bacon", "bunny meat").call
292
- end
293
-
294
- it "should verify method calls after the fact" do
295
- stub(subject).pig_rabbit
296
- lambda do
297
- received(subject).pig_rabbit("bacon", "bunny meat").call
298
- end.should raise_error(RR::Errors::SpyVerificationErrors::SpyVerificationError)
299
- end
300
- end
301
-
302
- class StrongTestObject
303
- def method_with_no_arguments
304
- end
305
-
306
- def method_with_one_argument(string)
307
- end
308
-
309
- def method_with_two_arguments(string, integer)
310
- end
311
-
312
- def method_with_three_arguments_including_varargs(string, integer, *args)
313
- end
314
-
315
- def method_with_varargs(*args)
316
- end
317
- end
318
-
319
- describe "strong" do
320
- context "when the method does not exist" do
321
- it "raises an exception" do
322
- lambda do
323
- strong.stub(StrongTestObject.new).something
324
- end.should raise_error(RR::Errors::SubjectDoesNotImplementMethodError)
325
- end
326
- end
327
-
328
- context "when the method exists with no arguments" do
329
- it "does not raise an exception" do
330
- strong.stub(StrongTestObject.new).method_with_no_arguments
331
- end
332
- end
333
-
334
- context "when the method has a different arity" do
335
- it "raises an exception" do
336
- lambda do
337
- strong.stub(StrongTestObject.new).method_with_one_argument
338
- end.should raise_error(RR::Errors::SubjectHasDifferentArityError)
339
- end
340
- end
341
-
342
- context "when the method has accepts a variable number of arguments" do
343
- it "does not raise an exception" do
344
- strong.stub(StrongTestObject.new).method_with_varargs
345
- end
346
- end
347
-
348
- context "when the method does not provide the required parameters before varargs" do
349
- it "raises an exception" do
350
- lambda do
351
- strong.stub(StrongTestObject.new).method_with_three_arguments_including_varargs
352
- end.should raise_error(RR::Errors::SubjectHasDifferentArityError)
353
- end
354
- end
355
-
356
- context "when the minimum number of parameters are provided" do
357
- it "does not raise an exception" do
358
- strong.stub(StrongTestObject.new).method_with_three_arguments_including_varargs("one", 2)
359
- end
360
- end
361
-
362
- context "when using instance_of and the method does not exist" do
363
- it "raises an exception" do
364
- lambda do
365
- strong.stub.instance_of(StrongTestObject).something
366
- StrongTestObject.new
367
- end.should raise_error(RR::Errors::SubjectDoesNotImplementMethodError)
368
- end
369
- end
370
-
371
- context "when using instance_of and the method does exist" do
372
- it "does not raise an exception" do
373
- strong.stub.instance_of(StrongTestObject).method_with_no_arguments
374
- end
375
- end
376
- end
377
-
378
- describe "spy" do
379
- it "should record all method invocations" do
380
- subject = Object.new
381
- def subject.something
382
- end
383
-
384
- def subject.something_else
385
- end
386
-
387
- spy(subject)
388
-
389
- subject.something
390
- subject.something_else
391
- subject.to_s
392
-
393
- received(subject).something.call
394
- received(subject).something_else.call
395
- received(subject).to_s.call
396
- end
397
- end
398
- end