flexmock 1.0.2 → 1.0.3

Sign up to get free protection for your applications and to get access to all the features.
data/lib/flexmock/core.rb CHANGED
@@ -197,9 +197,14 @@ class FlexMock
197
197
  # See Expectation for a list of declarators that can be used.
198
198
  #
199
199
  def should_receive(*args)
200
+ location = caller.first
201
+ flexmock_define_expectation(location, *args)
202
+ end
203
+
204
+ def flexmock_define_expectation(location, *args)
200
205
  @last_expectation = ContainerHelper.parse_should_args(self, args) do |sym|
201
206
  @expectations[sym] ||= ExpectationDirector.new(sym)
202
- result = Expectation.new(self, sym)
207
+ result = Expectation.new(self, sym, location)
203
208
  @expectations[sym] << result
204
209
  override_existing_method(sym) if flexmock_respond_to?(sym)
205
210
  result = ExplicitNeeded.new(result, sym, @base_class) if
@@ -15,6 +15,7 @@ class FlexMock
15
15
  class DefaultFrameworkAdapter
16
16
  def assert_block(msg, &block)
17
17
  unless yield
18
+ msg = msg.call if msg.is_a?(Proc)
18
19
  fail assertion_failed_error, msg
19
20
  end
20
21
  end
@@ -32,9 +32,10 @@ class FlexMock
32
32
  attr_accessor :mock
33
33
 
34
34
  # Create an expectation for a method named +sym+.
35
- def initialize(mock, sym)
35
+ def initialize(mock, sym, location)
36
36
  @mock = mock
37
37
  @sym = sym
38
+ @location = location
38
39
  @expected_args = nil
39
40
  @count_validators = []
40
41
  @count_validator_class = ExactCountValidator
@@ -392,6 +393,13 @@ class FlexMock
392
393
  expectations.defaultify_expectation(self) if expectations
393
394
  end
394
395
 
396
+ def flexmock_location_filter
397
+ yield
398
+ rescue Exception => ex
399
+ ex.backtrace.insert(0, @location)
400
+ raise ex
401
+ end
402
+
395
403
  end
396
404
 
397
405
  ##########################################################################
@@ -434,7 +442,7 @@ class FlexMock
434
442
  # Start a new method expectation. The following constraints will be
435
443
  # applied to the new expectation.
436
444
  def should_receive(*args, &block)
437
- @expectations.first.mock.should_receive(*args, &block)
445
+ @expectations.first.mock.flexmock_define_expectation(caller.first, *args, &block)
438
446
  end
439
447
 
440
448
  # Return a string representations
@@ -37,8 +37,8 @@ class FlexMock
37
37
  # criteria.
38
38
  def call(*args)
39
39
  exp = find_expectation(*args)
40
- FlexMock.check("no matching handler found for " +
41
- FlexMock.format_args(@sym, args)) { ! exp.nil? }
40
+ FlexMock.check(
41
+ "no matching handler found for " + FlexMock.format_args(@sym, args)) { ! exp.nil? }
42
42
  exp.verify_call(*args)
43
43
  end
44
44
 
@@ -117,6 +117,7 @@ class FlexMock
117
117
  # the mock object.
118
118
  #
119
119
  def flexmock(*args)
120
+ location = caller.first
120
121
  name = nil
121
122
  quick_defs = {}
122
123
  domain_obj = nil
@@ -160,10 +161,10 @@ class FlexMock
160
161
  result = mock
161
162
  end
162
163
  mock.flexmock_based_on(base_class) if base_class
163
- mock.should_receive(quick_defs)
164
+ mock.flexmock_define_expectation(location, quick_defs)
164
165
  yield(mock) if block_given?
165
166
  flexmock_remember(mock)
166
- ContainerHelper.add_model_methods(mock, model_class, id) if model_class
167
+ ContainerHelper.add_model_methods(mock, model_class, id, location) if model_class
167
168
  result
168
169
  end
169
170
  alias flexstub flexmock
@@ -230,29 +231,29 @@ class FlexMock
230
231
 
231
232
  # Automatically add mocks for some common methods in ActiveRecord
232
233
  # models.
233
- def add_model_methods(mock, model_class, id)
234
+ def add_model_methods(mock, model_class, id, location)
234
235
  container = mock.flexmock_container
235
236
 
236
237
  mock_errors = container.flexmock("errors")
237
- mock_errors.should_receive(:count).and_return(0).by_default
238
- mock_errors.should_receive(:full_messages).and_return([]).by_default
238
+ mock_errors.flexmock_define_expectation(location, :count).and_return(0).by_default
239
+ mock_errors.flexmock_define_expectation(location, :full_messages).and_return([]).by_default
239
240
 
240
- mock.should_receive(:id).and_return(id).by_default
241
- mock.should_receive(:to_params).and_return(id.to_s).by_default
242
- mock.should_receive(:new_record?).and_return(false).by_default
243
- mock.should_receive(:class).and_return(model_class).by_default
244
- mock.should_receive(:errors).and_return(mock_errors).by_default
241
+ mock.flexmock_define_expectation(location, :id).and_return(id).by_default
242
+ mock.flexmock_define_expectation(location, :to_params).and_return(id.to_s).by_default
243
+ mock.flexmock_define_expectation(location, :new_record?).and_return(false).by_default
244
+ mock.flexmock_define_expectation(location, :class).and_return(model_class).by_default
245
+ mock.flexmock_define_expectation(location, :errors).and_return(mock_errors).by_default
245
246
 
246
247
  # HACK: Ruby 1.9 needs the following lambda so that model_class
247
248
  # is correctly bound below.
248
249
  lambda { }
249
- mock.should_receive(:is_a?).with(any).and_return { |other|
250
+ mock.flexmock_define_expectation(location, :is_a?).with(any).and_return { |other|
250
251
  other == model_class
251
252
  }.by_default
252
- mock.should_receive(:instance_of?).with(any).and_return { |other|
253
+ mock.flexmock_define_expectation(location, :instance_of?).with(any).and_return { |other|
253
254
  other == model_class
254
255
  }.by_default
255
- mock.should_receive(:kind_of?).with(any).and_return { |other|
256
+ mock.flexmock_define_expectation(location, :kind_of?).with(any).and_return { |other|
256
257
  model_class.ancestors.include?(other)
257
258
  }.by_default
258
259
  end
@@ -33,6 +33,7 @@ class FlexMock
33
33
 
34
34
  MOCK_METHODS = [
35
35
  :should_receive, :new_instances,
36
+ :should_receive_with_location,
36
37
  :flexmock_get, :flexmock_teardown, :flexmock_verify,
37
38
  :flexmock_received?, :flexmock_calls,
38
39
  ]
@@ -79,11 +80,16 @@ class FlexMock
79
80
  #
80
81
  # See Expectation for a list of declarators that can be used.
81
82
  def should_receive(*args)
83
+ location = caller.first
84
+ flexmock_define_expectation(location, *args)
85
+ end
86
+
87
+ def flexmock_define_expectation(location, *args)
82
88
  ContainerHelper.parse_should_args(@mock, args) do |sym|
83
89
  unless @methods_proxied.include?(sym)
84
90
  hide_existing_method(sym)
85
91
  end
86
- ex = @mock.should_receive(sym)
92
+ ex = @mock.flexmock_define_expectation(location, sym)
87
93
  ex.mock = self
88
94
  ex
89
95
  end
@@ -123,14 +129,17 @@ class FlexMock
123
129
  #
124
130
  def new_instances(*allocators, &block)
125
131
  fail ArgumentError, "new_instances requires a Class to stub" unless Class === @obj
132
+ location = caller.first
126
133
  allocators = [:new] if allocators.empty?
127
134
  result = ExpectationRecorder.new
128
135
  allocators.each do |allocate_method|
129
136
  check_allocate_method(allocate_method)
130
- # HACK: Without the following lambda, Ruby 1.9 will not bind
131
- # the allocate_method parameter correctly.
137
+ # HACK: Without the following lambda, Some versions of Ruby 1.9
138
+ # would not bind the allocate_method parameter
139
+ # correctly. I don't think it is necessary for recent
140
+ # versions.
132
141
  lambda { }
133
- self.should_receive(allocate_method).and_return { |*args|
142
+ self.flexmock_define_expectation(location, allocate_method).and_return { |*args|
134
143
  new_obj = invoke_original(allocate_method, args)
135
144
  mock = flexmock_container.flexmock(new_obj)
136
145
  block.call(mock) if block_given?
@@ -57,7 +57,8 @@ class FlexMock
57
57
  # Record an expectation for receiving the method +sym+ with the
58
58
  # given arguments.
59
59
  def method_missing(sym, *args, &block)
60
- expectation = @mock.should_receive(sym).and_return(&block)
60
+ location = caller.first
61
+ expectation = @mock.flexmock_define_expectation(location, sym).and_return(&block)
61
62
  if strict?
62
63
  args = args.collect { |arg| eq(arg) }
63
64
  expectation.with(*args).ordered.once
@@ -22,6 +22,7 @@ class FlexMock
22
22
 
23
23
  class RSpecFrameworkAdapter
24
24
  def assert_block(msg, &block)
25
+ msg = msg.call if msg.is_a?(Proc)
25
26
  SpecModule::Expectations.fail_with(msg) unless yield
26
27
  end
27
28
 
@@ -19,9 +19,19 @@ class FlexMock
19
19
  result << times_description(options[:times])
20
20
  result << block_description(options[:with_block])
21
21
  result << ".\n"
22
- result << "The following messages have been received:\n"
23
- spy.flexmock_calls.each do |call_sym, call_args|
24
- result << " " << call_description(call_sym, call_args) << "\n"
22
+ result << describe_calls(spy)
23
+ result
24
+ end
25
+
26
+ def describe_calls(spy)
27
+ result = ''
28
+ if spy.flexmock_calls.empty?
29
+ result << "No messages have been received\n"
30
+ else
31
+ result << "The following messages have been received:\n"
32
+ spy.flexmock_calls.each do |call_sym, call_args|
33
+ result << " " << call_description(call_sym, call_args) << "\n"
34
+ end
25
35
  end
26
36
  result
27
37
  end
@@ -46,6 +46,17 @@ class FlexMock
46
46
  #
47
47
  class TestUnitFrameworkAdapter
48
48
  include Test::Unit::Assertions
49
+
50
+ def assert_block(msg, &block)
51
+ unless yield
52
+ msg = msg.call if msg.is_a?(Proc)
53
+ super(msg) { false }
54
+ end
55
+ rescue assertion_failed_error => ex
56
+ ex.message.sub!(/Expected block to return true value./,'')
57
+ raise ex
58
+ end
59
+
49
60
  def assertion_failed_error
50
61
  defined?(Test::Unit::AssertionFailedError) ? Test::Unit::AssertionFailedError : MiniTest::Assertion
51
62
  end
@@ -10,6 +10,7 @@
10
10
  #+++
11
11
 
12
12
  require 'flexmock/noop'
13
+ require 'flexmock/spy_describers'
13
14
 
14
15
  class FlexMock
15
16
 
@@ -17,6 +18,8 @@ class FlexMock
17
18
  # Base class for all the count validators.
18
19
  #
19
20
  class CountValidator
21
+ include FlexMock::SpyDescribers
22
+
20
23
  def initialize(expectation, limit)
21
24
  @exp = expectation
22
25
  @limit = limit
@@ -28,6 +31,10 @@ class FlexMock
28
31
  def eligible?(n)
29
32
  n < @limit
30
33
  end
34
+
35
+ def calls(n)
36
+ n == 1 ? "call" : "calls"
37
+ end
31
38
  end
32
39
 
33
40
  ####################################################################
@@ -37,8 +44,16 @@ class FlexMock
37
44
  # Validate that the method expectation was called exactly +n+
38
45
  # times.
39
46
  def validate(n)
40
- FlexMock.framework_adapter.assert_equal @limit, n,
41
- "method '#{@exp}' called incorrect number of times"
47
+ @exp.flexmock_location_filter do
48
+ FlexMock.framework_adapter.assert_block(
49
+ lambda {
50
+ "Method '#{@exp}' called incorrect number of times\n" +
51
+ "#{@limit} #{calls(@limit)} expected\n" +
52
+ "#{n} matching #{calls(n)} found\n" +
53
+ describe_calls(@exp.mock)
54
+ }
55
+ ) { @limit == n }
56
+ end
42
57
  end
43
58
  end
44
59
 
@@ -49,9 +64,15 @@ class FlexMock
49
64
  # Validate the method expectation was called no more than +n+
50
65
  # times.
51
66
  def validate(n)
52
- FlexMock.framework_adapter.assert_block(
53
- "Method '#{@exp}' should be called at least #{@limit} times,\n" +
54
- "only called #{n} times") { n >= @limit }
67
+ @exp.flexmock_location_filter do
68
+ FlexMock.framework_adapter.assert_block(
69
+ lambda {
70
+ "Method '#{@exp}' called incorrect number of times\n" +
71
+ "At least #{@limit} #{calls(@limit)} expected\n" +
72
+ "#{n} matching #{calls(n)} found\n" +
73
+ describe_calls(@exp.mock)
74
+ }) { n >= @limit }
75
+ end
55
76
  end
56
77
 
57
78
  # If the expectation has been called +n+ times, is it still
@@ -69,9 +90,15 @@ class FlexMock
69
90
  class AtMostCountValidator < CountValidator
70
91
  # Validate the method expectation was called at least +n+ times.
71
92
  def validate(n)
72
- FlexMock.framework_adapter.assert_block(
73
- "Method '#{@exp}' should be called at most #{@limit} times,\n" +
74
- "only called #{n} times") { n <= @limit }
93
+ @exp.flexmock_location_filter do
94
+ FlexMock.framework_adapter.assert_block(
95
+ lambda {
96
+ "Method '#{@exp}' called incorrect number of times\n" +
97
+ "At most #{@limit} #{calls(@limit)} expected\n" +
98
+ "#{n} matching #{calls(n)} found\n" +
99
+ describe_calls(@exp.mock)
100
+ }) { n <= @limit }
101
+ end
75
102
  end
76
103
  end
77
104
  end
@@ -3,7 +3,7 @@ class FlexMock
3
3
  NUMBERS = [
4
4
  MAJOR = 1,
5
5
  MINOR = 0,
6
- BUILD = 2,
6
+ BUILD = 3,
7
7
  ]
8
8
  end
9
9
 
@@ -76,6 +76,23 @@ class AssertSpyCalledTest < Test::Unit::TestCase
76
76
  end
77
77
  end
78
78
 
79
+ def test_assert_error_lists_calls_actually_made
80
+ spy.foo
81
+ spy.bar(1)
82
+ ex = assert_fails(/The following messages have been received/) do
83
+ assert_spy_called spy, :baz
84
+ end
85
+ assert_match(/ foo\(\)/, ex.message)
86
+ assert_match(/ bar\(1\)/, ex.message)
87
+ assert_no_match(/ baz\(\)/, ex.message)
88
+ end
89
+
90
+ def test_assert_errors_say_no_calls_made
91
+ ex = assert_fails(/No messages have been received/) do
92
+ assert_spy_called spy, :baz
93
+ end
94
+ end
95
+
79
96
  private
80
97
 
81
98
  def assert_fails(message_pattern)
@@ -21,10 +21,20 @@ class BaseClassTest < Test::Unit::TestCase
21
21
  @mock ||= flexmock(:on, FooBar)
22
22
  end
23
23
 
24
- def test_auto_mocks_class
24
+ def test_base_class_auto_mocks_class
25
25
  assert_equal FooBar, mock.class
26
26
  end
27
27
 
28
+ def test_base_class_auto_mocks_base_class_methods
29
+ assert_equal FlexMock.undefined, mock.foo
30
+ end
31
+
32
+ def test_base_class_does_not_mock_non_base_class_methods
33
+ assert_raise(NoMethodError) do
34
+ mock.fuzz
35
+ end
36
+ end
37
+
28
38
  def test_can_stub_existing_methods
29
39
  mock.should_receive(:foo => :bar)
30
40
  assert_equal :bar, mock.foo
@@ -65,7 +65,7 @@ class TestDemeterMocking < Test::Unit::TestCase
65
65
  def test_conflicting_mock_declarations_in_reverse_order_does_not_raise_error
66
66
  # Not all conflicting definitions can be detected.
67
67
  m = flexmock("A")
68
- assert_failure() do
68
+ assert_failure do
69
69
  m.should_receive("child.other").and_return(:other)
70
70
  m.should_receive("child").and_return(:xyzzy)
71
71
  assert_equal :xyzzy, m.child.other
@@ -96,7 +96,7 @@ class TestNewInstances < Test::Unit::TestCase
96
96
 
97
97
  Dog.new
98
98
  ex = assert_raise(assertion_failed_error) { flexmock_teardown }
99
- assert_match(/method 'bark\(.*\)' called incorrect number of times/, ex.message)
99
+ assert_match(/method 'bark\(.*\)' called incorrect number of times/i, ex.message)
100
100
  end
101
101
 
102
102
  def test_new_instances_reports_error_on_non_classes
@@ -71,7 +71,7 @@ class TestRecordMode < Test::Unit::TestCase
71
71
  end
72
72
 
73
73
  def test_recording_mode_should_validate_args_with_equals
74
- assert_failure do
74
+ assert_mock_failure(:deep => true, :line => __LINE__+5) do
75
75
  FlexMock.use("mock") do |mock|
76
76
  mock.should_expect do |r|
77
77
  r.f(1)
@@ -82,7 +82,7 @@ class TestRecordMode < Test::Unit::TestCase
82
82
  end
83
83
 
84
84
  def test_recording_mode_should_allow_arg_contraint_validation
85
- assert_failure do
85
+ assert_mock_failure(:deep => true, :line => __LINE__+5) do
86
86
  FlexMock.use("mock") do |mock|
87
87
  mock.should_expect do |r|
88
88
  r.f(1)
@@ -93,7 +93,7 @@ class TestRecordMode < Test::Unit::TestCase
93
93
  end
94
94
 
95
95
  def test_recording_mode_should_handle_multiplicity_contraints
96
- assert_failure do
96
+ assert_mock_failure(:line => __LINE__+3) do
97
97
  FlexMock.use("mock") do |mock|
98
98
  mock.should_expect do |r|
99
99
  r.f { :result }.once
@@ -105,7 +105,7 @@ class TestRecordMode < Test::Unit::TestCase
105
105
  end
106
106
 
107
107
  def test_strict_record_mode_requires_exact_argument_matches
108
- assert_failure do
108
+ assert_mock_failure(:deep => true, :line => __LINE__+6) do
109
109
  FlexMock.use("mock") do |mock|
110
110
  mock.should_expect do |rec|
111
111
  rec.should_be_strict
@@ -117,7 +117,7 @@ class TestRecordMode < Test::Unit::TestCase
117
117
  end
118
118
 
119
119
  def test_strict_record_mode_requires_exact_ordering
120
- assert_failure do
120
+ assert_mock_failure(:deep => true, :line => __LINE__+8) do
121
121
  FlexMock.use("mock") do |mock|
122
122
  mock.should_expect do |rec|
123
123
  rec.should_be_strict
@@ -131,7 +131,7 @@ class TestRecordMode < Test::Unit::TestCase
131
131
  end
132
132
 
133
133
  def test_strict_record_mode_requires_once
134
- assert_failure do
134
+ assert_mock_failure(:deep => true, :line => __LINE__+4) do
135
135
  FlexMock.use("mock") do |mock|
136
136
  mock.should_expect do |rec|
137
137
  rec.should_be_strict