rspec-mocks 2.0.0.beta.4 → 2.0.0.beta.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (43) hide show
  1. data/.autotest +3 -2
  2. data/VERSION +1 -1
  3. data/features/mocks/block_local_expectations.feature +0 -14
  4. data/features/mocks/mix_stubs_and_mocks.feature +2 -2
  5. data/features/mocks/warn_when_expectation_is_set_on_nil.feature +50 -0
  6. data/lib/rspec/mocks.rb +9 -9
  7. data/lib/rspec/mocks/argument_matchers.rb +1 -1
  8. data/lib/rspec/mocks/error_generator.rb +24 -8
  9. data/lib/rspec/mocks/framework.rb +1 -0
  10. data/lib/rspec/mocks/message_expectation.rb +1 -1
  11. data/lib/rspec/mocks/method_double.rb +156 -0
  12. data/lib/rspec/mocks/methods.rb +2 -2
  13. data/lib/rspec/mocks/mock.rb +17 -10
  14. data/lib/rspec/mocks/proxy.rb +71 -158
  15. data/lib/rspec/mocks/spec_methods.rb +19 -3
  16. data/rspec-mocks.gemspec +14 -10
  17. data/spec/rspec/mocks/any_number_of_times_spec.rb +1 -1
  18. data/spec/rspec/mocks/argument_expectation_spec.rb +2 -2
  19. data/spec/rspec/mocks/bug_report_10260_spec.rb +1 -1
  20. data/spec/rspec/mocks/bug_report_10263_spec.rb +8 -8
  21. data/spec/rspec/mocks/bug_report_15719_spec.rb +12 -12
  22. data/spec/rspec/mocks/bug_report_7611_spec.rb +1 -1
  23. data/spec/rspec/mocks/bug_report_7805_spec.rb +1 -1
  24. data/spec/rspec/mocks/bug_report_8165_spec.rb +1 -1
  25. data/spec/rspec/mocks/bug_report_957_spec.rb +1 -1
  26. data/spec/rspec/mocks/double_spec.rb +12 -0
  27. data/spec/rspec/mocks/failing_argument_matchers_spec.rb +7 -6
  28. data/spec/rspec/mocks/mock_ordering_spec.rb +54 -54
  29. data/spec/rspec/mocks/mock_space_spec.rb +4 -4
  30. data/spec/rspec/mocks/mock_spec.rb +55 -51
  31. data/spec/rspec/mocks/multiple_return_value_spec.rb +29 -7
  32. data/spec/rspec/mocks/nil_expectation_warning_spec.rb +8 -8
  33. data/spec/rspec/mocks/null_object_mock_spec.rb +2 -2
  34. data/spec/rspec/mocks/once_counts_spec.rb +1 -1
  35. data/spec/rspec/mocks/options_hash_spec.rb +1 -1
  36. data/spec/rspec/mocks/partial_mock_spec.rb +13 -7
  37. data/spec/rspec/mocks/passing_argument_matchers_spec.rb +1 -1
  38. data/spec/rspec/mocks/precise_counts_spec.rb +1 -1
  39. data/spec/rspec/mocks/record_messages_spec.rb +1 -1
  40. data/spec/rspec/mocks/stub_spec.rb +22 -22
  41. data/spec/rspec/mocks/stubbed_message_expectations_spec.rb +12 -12
  42. data/spec/rspec/mocks/twice_counts_spec.rb +1 -1
  43. metadata +13 -9
@@ -1,29 +1,36 @@
1
1
  module Rspec
2
2
  module Mocks
3
3
  class Proxy
4
- DEFAULT_OPTIONS = {
5
- :null_object => false,
6
- }
4
+ DEFAULT_OPTIONS = { :null_object => false }
5
+
6
+ class << self
7
+ def warn_about_expectations_on_nil
8
+ defined?(@warn_about_expectations_on_nil) ? @warn_about_expectations_on_nil : true
9
+ end
7
10
 
8
- @@warn_about_expectations_on_nil = true
11
+ def warn_about_expectations_on_nil=(new_value)
12
+ @warn_about_expectations_on_nil = new_value
13
+ end
9
14
 
10
- def self.allow_message_expectations_on_nil
11
- @@warn_about_expectations_on_nil = false
12
-
13
- # ensure nil.rspec_verify is called even if an expectation is not set in the example
14
- # otherwise the allowance would effect subsequent examples
15
- $rspec_mocks.add(nil) unless $rspec_mocks.nil?
15
+ def allow_message_expectations_on_nil
16
+ @warn_about_expectations_on_nil = false
17
+
18
+ # ensure nil.rspec_verify is called even if an expectation is not set in the example
19
+ # otherwise the allowance would effect subsequent examples
20
+ $rspec_mocks.add(nil) unless $rspec_mocks.nil?
21
+ end
22
+
23
+ def allow_message_expectations_on_nil?
24
+ !warn_about_expectations_on_nil
25
+ end
16
26
  end
17
27
 
18
- def initialize(target, name=nil, options={})
19
- @target = target
28
+ def initialize(object, name=nil, options={})
29
+ @object = object
20
30
  @name = name
21
- @error_generator = ErrorGenerator.new target, name
31
+ @error_generator = ErrorGenerator.new object, name, options
22
32
  @expectation_ordering = OrderGroup.new @error_generator
23
- @expectations = []
24
33
  @messages_received = []
25
- @stubs = []
26
- @proxied_methods = []
27
34
  @options = options ? DEFAULT_OPTIONS.dup.merge(options) : DEFAULT_OPTIONS
28
35
  @already_proxied_respond_to = false
29
36
  end
@@ -34,197 +41,103 @@ module Rspec
34
41
 
35
42
  def as_null_object
36
43
  @options[:null_object] = true
37
- @target
44
+ @object
38
45
  end
39
46
 
40
- def add_message_expectation(expected_from, sym, opts={}, &block)
41
- __add sym
42
- warn_if_nil_class sym
43
- if existing_stub = @stubs.detect {|s| s.sym == sym }
44
- expectation = existing_stub.build_child(expected_from, block_given?? block : nil, 1, opts)
45
- else
46
- expectation = MessageExpectation.new(@error_generator, @expectation_ordering, expected_from, sym, block_given? ? block : nil, 1, opts)
47
- end
48
- @expectations << expectation
49
- @expectations.last
47
+ def already_proxied_respond_to
48
+ @already_proxied_respond_to = true
49
+ end
50
+
51
+ def already_proxied_respond_to?
52
+ @already_proxied_respond_to
53
+ end
54
+
55
+ def add_message_expectation(location, method_name, opts={}, &block)
56
+ method_double[method_name].add_expectation @error_generator, @expectation_ordering, location, opts, &block
50
57
  end
51
58
 
52
- def add_negative_message_expectation(expected_from, sym, &block)
53
- __add sym
54
- warn_if_nil_class sym
55
- @expectations << NegativeMessageExpectation.new(@error_generator, @expectation_ordering, expected_from, sym, block_given? ? block : nil)
56
- @expectations.last
59
+ def add_negative_message_expectation(location, method_name, &implementation)
60
+ method_double[method_name].add_negative_expectation @error_generator, @expectation_ordering, location, &implementation
57
61
  end
58
62
 
59
- def add_stub(expected_from, sym, opts={}, &implementation)
60
- __add sym
61
- @stubs.unshift MessageExpectation.new(@error_generator, @expectation_ordering, expected_from, sym, nil, :any, opts, &implementation)
62
- @stubs.first
63
+ def add_stub(location, method_name, opts={}, &implementation)
64
+ method_double[method_name].add_stub @error_generator, @expectation_ordering, location, opts, &implementation
63
65
  end
64
66
 
65
67
  def verify #:nodoc:
66
- verify_expectations
68
+ method_doubles.each {|d| d.verify}
67
69
  ensure
68
70
  reset
69
71
  end
70
72
 
71
73
  def reset
72
- clear_expectations
73
- clear_stubs
74
- reset_proxied_methods
75
- clear_proxied_methods
76
- reset_nil_expectations_warning
74
+ method_doubles.each {|d| d.reset}
77
75
  end
78
76
 
79
- def received_message?(sym, *args, &block)
80
- @messages_received.any? {|array| array == [sym, args, block]}
77
+ def received_message?(method_name, *args, &block)
78
+ @messages_received.any? {|array| array == [method_name, args, block]}
81
79
  end
82
80
 
83
- def has_negative_expectation?(sym)
84
- @expectations.detect {|expectation| expectation.negative_expectation_for?(sym)}
81
+ def has_negative_expectation?(method_name)
82
+ method_double[method_name].expectations.detect {|expectation| expectation.negative_expectation_for?(method_name)}
85
83
  end
86
84
 
87
- def record_message_received(sym, args, block)
88
- @messages_received << [sym, args, block]
85
+ def record_message_received(method_name, args, block)
86
+ @messages_received << [method_name, args, block]
89
87
  end
90
88
 
91
- def message_received(sym, *args, &block)
92
- expectation = find_matching_expectation(sym, *args)
93
- stub = find_matching_method_stub(sym, *args)
89
+ def message_received(method_name, *args, &block)
90
+ expectation = find_matching_expectation(method_name, *args)
91
+ stub = find_matching_method_stub(method_name, *args)
94
92
 
95
93
  if (stub && expectation && expectation.called_max_times?) || (stub && !expectation)
96
- if expectation = find_almost_matching_expectation(sym, *args)
94
+ if expectation = find_almost_matching_expectation(method_name, *args)
97
95
  expectation.advise(args, block) unless expectation.expected_messages_received?
98
96
  end
99
97
  stub.invoke(args, block)
100
98
  elsif expectation
101
99
  expectation.invoke(args, block)
102
- elsif expectation = find_almost_matching_expectation(sym, *args)
100
+ elsif expectation = find_almost_matching_expectation(method_name, *args)
103
101
  expectation.advise(args, block) if null_object? unless expectation.expected_messages_received?
104
- raise_unexpected_message_args_error(expectation, *args) unless (has_negative_expectation?(sym) or null_object?)
105
- elsif @target.is_a?(Class)
106
- @target.superclass.send(sym, *args, &block)
102
+ raise_unexpected_message_args_error(expectation, *args) unless (has_negative_expectation?(method_name) or null_object?)
103
+ elsif @object.is_a?(Class)
104
+ @object.superclass.send(method_name, *args, &block)
107
105
  else
108
- @target.__send__ :method_missing, sym, *args, &block
106
+ @object.__send__ :method_missing, method_name, *args, &block
109
107
  end
110
108
  end
111
109
 
112
110
  def raise_unexpected_message_args_error(expectation, *args)
113
- @error_generator.raise_unexpected_message_args_error expectation, *args
111
+ @error_generator.raise_unexpected_message_args_error(expectation, *args)
114
112
  end
115
113
 
116
- def raise_unexpected_message_error(sym, *args)
117
- @error_generator.raise_unexpected_message_error sym, *args
114
+ def raise_unexpected_message_error(method_name, *args)
115
+ @error_generator.raise_unexpected_message_error method_name, *args
118
116
  end
119
117
 
120
118
  private
121
119
 
122
- def __add(sym)
123
- $rspec_mocks.add(@target) unless $rspec_mocks.nil?
124
- define_expected_method(sym)
125
- end
126
-
127
- def warn_if_nil_class(sym)
128
- if proxy_for_nil_class? & @@warn_about_expectations_on_nil
129
- Kernel.warn("An expectation of :#{sym} was set on nil. Called from #{caller[2]}. Use allow_message_expectations_on_nil to disable warnings.")
130
- end
131
- end
132
-
133
- def define_expected_method(sym)
134
- unless @proxied_methods.include?(sym)
135
- visibility_string = "#{visibility(sym)} :#{sym}"
136
- if target_responds_to?(sym)
137
- munged_sym = munge(sym)
138
- target_metaclass.instance_eval do
139
- alias_method munged_sym, sym if method_defined?(sym)
140
- end
141
- @proxied_methods << sym
142
- end
143
- target_metaclass.class_eval(<<-EOF, __FILE__, __LINE__)
144
- def #{sym}(*args, &block)
145
- __mock_proxy.message_received :#{sym}, *args, &block
146
- end
147
- #{visibility_string}
148
- EOF
149
- end
150
- end
151
-
152
- def target_responds_to?(sym)
153
- return @target.__send__(munge(:respond_to?),sym) if @already_proxied_respond_to
154
- return @already_proxied_respond_to = true if sym == :respond_to?
155
- return @target.respond_to?(sym, true)
156
- end
157
-
158
- def visibility(sym)
159
- if Mock === @target
160
- 'public'
161
- elsif target_metaclass.private_method_defined?(sym)
162
- 'private'
163
- elsif target_metaclass.protected_method_defined?(sym)
164
- 'protected'
165
- else
166
- 'public'
167
- end
168
- end
169
-
170
- def munge(sym)
171
- "proxied_by_rspec__#{sym}"
172
- end
173
-
174
- def clear_expectations
175
- @expectations.clear
176
- end
177
-
178
- def clear_stubs
179
- @stubs.clear
180
- end
181
-
182
- def clear_proxied_methods
183
- @proxied_methods.clear
120
+ def method_double
121
+ @method_double ||= Hash.new {|h,k|
122
+ h[k] = MethodDouble.new(@object, k, self)
123
+ }
184
124
  end
185
125
 
186
- def target_metaclass
187
- class << @target; self; end
188
- end
189
-
190
- def verify_expectations
191
- @expectations.each do |expectation|
192
- expectation.verify_messages_received
193
- end
194
- end
195
-
196
- def reset_proxied_methods
197
- @proxied_methods.each do |sym|
198
- munged_sym = munge(sym)
199
- target_metaclass.instance_eval do
200
- remove_method sym
201
- if method_defined?(munged_sym)
202
- alias_method sym, munged_sym
203
- remove_method munged_sym
204
- end
205
- end
206
- end
207
- end
208
-
209
- def proxy_for_nil_class?
210
- @target.nil?
126
+ def method_doubles
127
+ method_double.values
211
128
  end
212
129
 
213
- def reset_nil_expectations_warning
214
- @@warn_about_expectations_on_nil = true if proxy_for_nil_class?
215
- end
216
-
217
- def find_matching_expectation(sym, *args)
218
- @expectations.find {|expectation| expectation.matches(sym, args) && !expectation.called_max_times?} ||
219
- @expectations.find {|expectation| expectation.matches(sym, args)}
130
+ def find_matching_expectation(method_name, *args)
131
+ method_double[method_name].expectations.find {|expectation| expectation.matches(method_name, args) && !expectation.called_max_times?} ||
132
+ method_double[method_name].expectations.find {|expectation| expectation.matches(method_name, args)}
220
133
  end
221
134
 
222
- def find_almost_matching_expectation(sym, *args)
223
- @expectations.find {|expectation| expectation.matches_name_but_not_args(sym, args)}
135
+ def find_almost_matching_expectation(method_name, *args)
136
+ method_double[method_name].expectations.find {|expectation| expectation.matches_name_but_not_args(method_name, args)}
224
137
  end
225
138
 
226
- def find_matching_method_stub(sym, *args)
227
- @stubs.find {|stub| stub.matches(sym, args)}
139
+ def find_matching_method_stub(method_name, *args)
140
+ method_double[method_name].stubs.find {|stub| stub.matches(method_name, args)}
228
141
  end
229
142
 
230
143
  end
@@ -14,17 +14,25 @@ module Rspec
14
14
  #
15
15
  # == Examples
16
16
  #
17
- # stub_thing = mock("thing", :a => "A")
17
+ # stub_thing = double("thing", :a => "A")
18
18
  # stub_thing.a == "A" => true
19
19
  #
20
20
  # stub_person = stub("thing", :name => "Joe", :email => "joe@domain.com")
21
21
  # stub_person.name => "Joe"
22
22
  # stub_person.email => "joe@domain.com"
23
+ def double(*args)
24
+ declare_double('Double', *args)
25
+ end
26
+
27
+ # Just like double, but use double
23
28
  def mock(*args)
24
- Rspec::Mocks::Mock.new(*args)
29
+ declare_double('Mock', *args)
25
30
  end
26
31
 
27
- alias :stub :mock
32
+ # Just like double, but use double
33
+ def stub(*args)
34
+ declare_double('Stub', *args)
35
+ end
28
36
 
29
37
  # Disables warning messages about expectations being set on nil.
30
38
  #
@@ -34,6 +42,14 @@ module Rspec
34
42
  Proxy.allow_message_expectations_on_nil
35
43
  end
36
44
 
45
+ private
46
+
47
+ def declare_double(declared_as, *args) # :nodoc:
48
+ args << {} unless Hash === args.last
49
+ args.last[:__declared_as] = declared_as
50
+ Rspec::Mocks::Mock.new(*args)
51
+ end
52
+
37
53
  end
38
54
  end
39
55
  end
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{rspec-mocks}
8
- s.version = "2.0.0.beta.4"
8
+ s.version = "2.0.0.beta.5"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new("> 1.3.1") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["David Chelimsky", "Chad Humphries"]
12
- s.date = %q{2010-03-15}
12
+ s.date = %q{2010-04-04}
13
13
  s.description = %q{Rspec's 'test double' framework, with support for stubbing and mocking}
14
14
  s.email = %q{dchelimsky@gmail.com;chad.humphries@gmail.com}
15
15
  s.extra_rdoc_files = [
@@ -27,6 +27,7 @@ Gem::Specification.new do |s|
27
27
  "cucumber.yml",
28
28
  "features/mocks/block_local_expectations.feature",
29
29
  "features/mocks/mix_stubs_and_mocks.feature",
30
+ "features/mocks/warn_when_expectation_is_set_on_nil.feature",
30
31
  "features/stubs/stub_implementation.feature",
31
32
  "features/support/env.rb",
32
33
  "lib/rspec/mocks.rb",
@@ -39,6 +40,7 @@ Gem::Specification.new do |s|
39
40
  "lib/rspec/mocks/extensions/object.rb",
40
41
  "lib/rspec/mocks/framework.rb",
41
42
  "lib/rspec/mocks/message_expectation.rb",
43
+ "lib/rspec/mocks/method_double.rb",
42
44
  "lib/rspec/mocks/methods.rb",
43
45
  "lib/rspec/mocks/mock.rb",
44
46
  "lib/rspec/mocks/order_group.rb",
@@ -66,6 +68,7 @@ Gem::Specification.new do |s|
66
68
  "spec/rspec/mocks/bug_report_8302_spec.rb",
67
69
  "spec/rspec/mocks/bug_report_830_spec.rb",
68
70
  "spec/rspec/mocks/bug_report_957_spec.rb",
71
+ "spec/rspec/mocks/double_spec.rb",
69
72
  "spec/rspec/mocks/failing_argument_matchers_spec.rb",
70
73
  "spec/rspec/mocks/hash_including_matcher_spec.rb",
71
74
  "spec/rspec/mocks/hash_not_including_matcher_spec.rb",
@@ -94,7 +97,7 @@ Gem::Specification.new do |s|
94
97
  s.homepage = %q{http://github.com/rspec/mocks}
95
98
  s.post_install_message = %q{**************************************************
96
99
 
97
- Thank you for installing rspec-mocks-2.0.0.beta.4
100
+ Thank you for installing rspec-mocks-2.0.0.beta.5
98
101
 
99
102
  This is beta software. If you are looking
100
103
  for a supported production release, please
@@ -106,7 +109,7 @@ Gem::Specification.new do |s|
106
109
  s.require_paths = ["lib"]
107
110
  s.rubyforge_project = %q{rspec}
108
111
  s.rubygems_version = %q{1.3.6}
109
- s.summary = %q{rspec-mocks-2.0.0.beta.4}
112
+ s.summary = %q{rspec-mocks-2.0.0.beta.5}
110
113
  s.test_files = [
111
114
  "spec/rspec/mocks/and_yield_spec.rb",
112
115
  "spec/rspec/mocks/any_number_of_times_spec.rb",
@@ -126,6 +129,7 @@ Gem::Specification.new do |s|
126
129
  "spec/rspec/mocks/bug_report_8302_spec.rb",
127
130
  "spec/rspec/mocks/bug_report_830_spec.rb",
128
131
  "spec/rspec/mocks/bug_report_957_spec.rb",
132
+ "spec/rspec/mocks/double_spec.rb",
129
133
  "spec/rspec/mocks/failing_argument_matchers_spec.rb",
130
134
  "spec/rspec/mocks/hash_including_matcher_spec.rb",
131
135
  "spec/rspec/mocks/hash_not_including_matcher_spec.rb",
@@ -156,15 +160,15 @@ Gem::Specification.new do |s|
156
160
  s.specification_version = 3
157
161
 
158
162
  if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
159
- s.add_development_dependency(%q<rspec-core>, ["= 2.0.0.beta.4"])
160
- s.add_development_dependency(%q<rspec-expectations>, ["= 2.0.0.beta.4"])
163
+ s.add_development_dependency(%q<rspec-core>, ["= 2.0.0.beta.5"])
164
+ s.add_development_dependency(%q<rspec-expectations>, ["= 2.0.0.beta.5"])
161
165
  else
162
- s.add_dependency(%q<rspec-core>, ["= 2.0.0.beta.4"])
163
- s.add_dependency(%q<rspec-expectations>, ["= 2.0.0.beta.4"])
166
+ s.add_dependency(%q<rspec-core>, ["= 2.0.0.beta.5"])
167
+ s.add_dependency(%q<rspec-expectations>, ["= 2.0.0.beta.5"])
164
168
  end
165
169
  else
166
- s.add_dependency(%q<rspec-core>, ["= 2.0.0.beta.4"])
167
- s.add_dependency(%q<rspec-expectations>, ["= 2.0.0.beta.4"])
170
+ s.add_dependency(%q<rspec-core>, ["= 2.0.0.beta.5"])
171
+ s.add_dependency(%q<rspec-expectations>, ["= 2.0.0.beta.5"])
168
172
  end
169
173
  end
170
174
 
@@ -25,7 +25,7 @@ module Rspec
25
25
  end
26
26
 
27
27
  it "should return the mocked value when called after a similar stub" do
28
- @mock.stub!(:message).and_return :stub_value
28
+ @mock.stub(:message).and_return :stub_value
29
29
  @mock.should_receive(:message).any_number_of_times.and_return(:mock_value)
30
30
  @mock.message.should == :mock_value
31
31
  @mock.message.should == :mock_value
@@ -5,7 +5,7 @@ module Rspec
5
5
  describe ArgumentExpectation do
6
6
  it "should consider an object that responds to #matches? and #description to be a matcher" do
7
7
  argument_expecatation = Rspec::Mocks::ArgumentExpectation.new([])
8
- obj = mock("matcher")
8
+ obj = double("matcher")
9
9
  obj.should_receive(:respond_to?).with(:matches?).and_return(true)
10
10
  obj.should_receive(:respond_to?).with(:description).and_return(true)
11
11
  argument_expecatation.is_matcher?(obj).should be_true
@@ -13,7 +13,7 @@ module Rspec
13
13
 
14
14
  it "should NOT consider an object that only responds to #matches? to be a matcher" do
15
15
  argument_expecatation = Rspec::Mocks::ArgumentExpectation.new([])
16
- obj = mock("matcher")
16
+ obj = double("matcher")
17
17
  obj.should_receive(:respond_to?).with(:matches?).and_return(true)
18
18
  obj.should_receive(:respond_to?).with(:description).and_return(false)
19
19
  argument_expecatation.is_matcher?(obj).should be_false