flexmock 1.0.2 → 1.0.3

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/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