flexmock 0.6.4 → 0.7.0
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 +8 -0
- data/README +116 -3
- data/Rakefile +5 -5
- data/TAGS +396 -282
- data/doc/releases/flexmock-0.7.0.rdoc +138 -0
- data/lib/flexmock/base.rb +2 -1
- data/lib/flexmock/core.rb +30 -29
- data/lib/flexmock/core_class_methods.rb +21 -30
- data/lib/flexmock/deprecated_methods.rb +62 -0
- data/lib/flexmock/expectation.rb +101 -21
- data/lib/flexmock/expectation_director.rb +10 -5
- data/lib/flexmock/mock_container.rb +144 -29
- data/lib/flexmock/ordering.rb +51 -0
- data/lib/flexmock/partial_mock.rb +23 -22
- data/test/asserts.rb +34 -0
- data/test/redirect_error.rb +16 -0
- data/test/rspec_integration/integration_spec.rb +6 -0
- data/test/test_demeter_mocking.rb +129 -0
- data/test/{test_mock.rb → test_deprecated_methods.rb} +64 -17
- data/test/test_example.rb +4 -3
- data/test/test_extended_should_receive.rb +1 -1
- data/test/test_flexmodel.rb +17 -1
- data/test/test_naming.rb +43 -8
- data/test/test_new_instances.rb +2 -22
- data/test/test_partial_mock.rb +19 -19
- data/test/test_record_mode.rb +27 -38
- data/test/test_should_receive.rb +199 -27
- metadata +11 -4
@@ -0,0 +1,138 @@
|
|
1
|
+
= FlexMock 0.7.0 Released
|
2
|
+
|
3
|
+
FlexMock is a flexible mocking library for use in unit testing and behavior
|
4
|
+
specification in Ruby. Version 0.7.0 introduces several enhancements.
|
5
|
+
|
6
|
+
== New in 0.7.0
|
7
|
+
|
8
|
+
* FlexMock now supports the ability to mock a chain of method calls
|
9
|
+
automatically. For example:
|
10
|
+
|
11
|
+
car = flexmock("car", "chassis.engine.piston.stroke" => :ok)
|
12
|
+
assert_equal :ok, car.chassis.engine.piston.stroke
|
13
|
+
|
14
|
+
will create a sequence of mocks so that the "chassis" call will
|
15
|
+
return a mock that responds to "engine", which returns a mock that
|
16
|
+
responds to "piston", which returns a mock that responds to
|
17
|
+
"stroke". This facility makes mocking legacy code that violates the
|
18
|
+
Law of Demeter a bit easier to deal with.
|
19
|
+
|
20
|
+
* Added the the +and_yield+ constraint to FlexMock expectations. This
|
21
|
+
allows the user to easily specify values passed to any block given
|
22
|
+
to the mock method.
|
23
|
+
|
24
|
+
* Globally ordering of mocked calls is now optionally available. When
|
25
|
+
a mock method is globally ordered, it must be called in the correct
|
26
|
+
order with regard to all other globally ordered methods. Non-global
|
27
|
+
ordering only requires that the method calls be ordered with regard
|
28
|
+
to other methods on the same mock object.
|
29
|
+
|
30
|
+
* The output for mock.inspect was modified to be much more consise, so
|
31
|
+
that test framework error messages do not overwhelm the output.
|
32
|
+
|
33
|
+
* In order to clean up the method namespace, a number of internally
|
34
|
+
used methods were deprecated. All non-public methods that get added
|
35
|
+
to mocks, partial mocks or test frameworks now begin with
|
36
|
+
"flexmock_" (rather than "mock_"). The "mock_*" versions are still
|
37
|
+
available, but will display deprecation warnings when used. The
|
38
|
+
deprecated "mock_*" methods will be removed in a future version.
|
39
|
+
|
40
|
+
* Additionally, the ancient "mock_handle" method has been deprecated
|
41
|
+
(prints a warning when used), and will be removed in a future
|
42
|
+
version. Users are encouraged to use the newer "should_receive"
|
43
|
+
method instead.
|
44
|
+
|
45
|
+
== New Features Added in 0.6.x
|
46
|
+
|
47
|
+
In case you missed them, here are a number of features that were added
|
48
|
+
during the 0.6.x versions of FlexMock.
|
49
|
+
|
50
|
+
* ActiveRecord mocking support with flexmock(:model, ModelName).
|
51
|
+
|
52
|
+
* Better partial mock definitions, including a "safe-mode" that
|
53
|
+
minimizes mock namespace pollution in the domain object.
|
54
|
+
|
55
|
+
* Support for +and_raise+ constraint to ease the definition of mocks
|
56
|
+
that raise exceptions.
|
57
|
+
|
58
|
+
== What is FlexMock?
|
59
|
+
|
60
|
+
FlexMock is a flexible framework for creating mock object for testing. When
|
61
|
+
running unit tests, it is often desirable to use isolate the objects being
|
62
|
+
tested from the "real world" by having them interact with simplified test
|
63
|
+
objects. Sometimes these test objects simply return values when called, other
|
64
|
+
times they verify that certain methods were called with particular arguments
|
65
|
+
in a particular order.
|
66
|
+
|
67
|
+
FlexMock makes creating these test objects easy.
|
68
|
+
|
69
|
+
=== Features
|
70
|
+
|
71
|
+
* Easy integration with both Test::Unit and RSpec. Mocks created with the
|
72
|
+
flexmock method are automatically verified at the end of the test or
|
73
|
+
example.
|
74
|
+
|
75
|
+
* A fluent interface that allows mock behavior to be specified very
|
76
|
+
easily.
|
77
|
+
|
78
|
+
* A "record mode" where an existing implementation can record its
|
79
|
+
interaction with a mock for later validation against a new
|
80
|
+
implementation.
|
81
|
+
|
82
|
+
* Easy mocking of individual methods in existing, non-mock objects.
|
83
|
+
|
84
|
+
* The ability to cause classes to instantiate test instances (instead of real
|
85
|
+
instances) for the duration of a test.
|
86
|
+
|
87
|
+
=== Example
|
88
|
+
|
89
|
+
Suppose you had a Dog object that wagged a tail when it was happy.
|
90
|
+
Something like this:
|
91
|
+
|
92
|
+
class Dog
|
93
|
+
def initialize(a_tail)
|
94
|
+
@tail = a_tail
|
95
|
+
end
|
96
|
+
def happy
|
97
|
+
@tail.wag
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
To test the +Dog+ class without a real +Tail+ object (perhaps because
|
102
|
+
real +Tail+ objects activate servos in some robotic equipment), you
|
103
|
+
can do something like this:
|
104
|
+
|
105
|
+
require 'test/unit'
|
106
|
+
require 'flexmock/test_unit'
|
107
|
+
|
108
|
+
class TestDog < Test::Unit::TestCase
|
109
|
+
def test_dog_wags_tail_when_happy
|
110
|
+
tail = flexmock("tail")
|
111
|
+
tail.should_receive(:wag).once
|
112
|
+
dog = Dog.new(tail)
|
113
|
+
dog.happy
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
FlexMock will automatically verify that the mocked tail object received the
|
118
|
+
message +wag+ exactly one time. If it doesn't, the test will not pass.
|
119
|
+
|
120
|
+
See the FlexMock documentation at http://flexmock.rubyforge.org for details on
|
121
|
+
specifying arguments and return values on mocked methods, as well as a simple
|
122
|
+
technique for mocking tail objects when the Dog class creates the tail objects
|
123
|
+
directly.
|
124
|
+
|
125
|
+
== Availability
|
126
|
+
|
127
|
+
You can make sure you have the latest version with a quick RubyGems command:
|
128
|
+
|
129
|
+
gem install flexmock (you may need root/admin privileges)
|
130
|
+
|
131
|
+
Otherwise, you can get it from the more traditional places:
|
132
|
+
|
133
|
+
Download:: http://rubyforge.org/project/showfiles.php?group_id=170
|
134
|
+
|
135
|
+
You will find documentation at: http://flexmock.rubyforge.org.
|
136
|
+
|
137
|
+
-- Jim Weirich
|
138
|
+
|
data/lib/flexmock/base.rb
CHANGED
data/lib/flexmock/core.rb
CHANGED
@@ -10,6 +10,7 @@
|
|
10
10
|
#+++
|
11
11
|
|
12
12
|
require 'flexmock/composite'
|
13
|
+
require 'flexmock/ordering'
|
13
14
|
|
14
15
|
######################################################################
|
15
16
|
# FlexMock is a flexible mock object framework for supporting testing.
|
@@ -42,55 +43,49 @@ require 'flexmock/composite'
|
|
42
43
|
# call +super+.
|
43
44
|
#
|
44
45
|
class FlexMock
|
46
|
+
include Ordering
|
45
47
|
|
46
48
|
# Error raised when flexmock is used incorrectly.
|
47
49
|
class UsageError < RuntimeError
|
48
50
|
end
|
49
51
|
|
50
|
-
|
51
|
-
|
52
|
+
class MockError < RuntimeError
|
53
|
+
end
|
54
|
+
|
55
|
+
attr_reader :flexmock_name
|
56
|
+
attr_accessor :flexmock_container
|
52
57
|
|
53
58
|
# Create a FlexMock object with the given name. The name is used in
|
54
|
-
# error messages.
|
55
|
-
|
56
|
-
|
59
|
+
# error messages. If no container is given, create a new, one-off
|
60
|
+
# container for this mock.
|
61
|
+
def initialize(name="unknown", container=nil)
|
62
|
+
@flexmock_name = name
|
57
63
|
@expectations = Hash.new
|
58
|
-
@allocated_order = 0
|
59
|
-
@mock_current_order = 0
|
60
|
-
@mock_container = nil
|
61
|
-
@mock_groups = {}
|
62
64
|
@ignore_missing = false
|
63
65
|
@verified = false
|
66
|
+
container = UseContainer.new if container.nil?
|
67
|
+
container.flexmock_remember(self)
|
64
68
|
end
|
65
69
|
|
66
|
-
#
|
67
|
-
|
68
|
-
|
69
|
-
# that by passing in the number of expected calls as a second
|
70
|
-
# paramter.
|
71
|
-
def mock_handle(sym, expected_count=nil, &block) # :nodoc:
|
72
|
-
self.should_receive(sym).times(expected_count).returns(&block)
|
70
|
+
# Return the inspection string for a mock.
|
71
|
+
def inspect
|
72
|
+
"<FlexMock:#{flexmock_name}>"
|
73
73
|
end
|
74
74
|
|
75
75
|
# Verify that each method that had an explicit expected count was
|
76
76
|
# actually called that many times.
|
77
|
-
def
|
77
|
+
def flexmock_verify
|
78
78
|
return if @verified
|
79
79
|
@verified = true
|
80
|
-
|
80
|
+
flexmock_wrap do
|
81
81
|
@expectations.each do |sym, handler|
|
82
|
-
handler.
|
82
|
+
handler.flexmock_verify
|
83
83
|
end
|
84
84
|
end
|
85
85
|
end
|
86
86
|
|
87
87
|
# Teardown and infrastructure setup for this mock.
|
88
|
-
def
|
89
|
-
end
|
90
|
-
|
91
|
-
# Allocation a new order number from the mock.
|
92
|
-
def mock_allocate_order
|
93
|
-
@allocated_order += 1
|
88
|
+
def flexmock_teardown
|
94
89
|
end
|
95
90
|
|
96
91
|
# Ignore all undefined (missing) method calls.
|
@@ -101,7 +96,7 @@ class FlexMock
|
|
101
96
|
|
102
97
|
# Handle missing methods by attempting to look up a handler.
|
103
98
|
def method_missing(sym, *args, &block)
|
104
|
-
|
99
|
+
flexmock_wrap do
|
105
100
|
if handler = @expectations[sym]
|
106
101
|
args << block if block_given?
|
107
102
|
handler.call(*args)
|
@@ -119,6 +114,12 @@ class FlexMock
|
|
119
114
|
super || (@expectations[sym] ? true : @ignore_missing)
|
120
115
|
end
|
121
116
|
|
117
|
+
# Find the mock expectation for method sym and arguments.
|
118
|
+
def flexmock_find_expectation(sym, *args)
|
119
|
+
exp = @expectations[sym]
|
120
|
+
exp ? exp.find_expectation(*args) : nil
|
121
|
+
end
|
122
|
+
|
122
123
|
# Override the built-in +method+ to include the mocked methods.
|
123
124
|
def method(sym)
|
124
125
|
@expectations[sym] || super
|
@@ -150,7 +151,7 @@ class FlexMock
|
|
150
151
|
# See Expectation for a list of declarators that can be used.
|
151
152
|
#
|
152
153
|
def should_receive(*args)
|
153
|
-
|
154
|
+
ContainerHelper.parse_should_args(self, args) do |sym|
|
154
155
|
@expectations[sym] ||= ExpectationDirector.new(sym)
|
155
156
|
result = Expectation.new(self, sym)
|
156
157
|
@expectations[sym] << result
|
@@ -179,11 +180,11 @@ class FlexMock
|
|
179
180
|
|
180
181
|
# Wrap a block of code so the any assertion errors are wrapped so
|
181
182
|
# that the mock name is added to the error message .
|
182
|
-
def
|
183
|
+
def flexmock_wrap(&block)
|
183
184
|
yield
|
184
185
|
rescue FlexMock.framework_adapter.assertion_failed_error => ex
|
185
186
|
raise FlexMock.framework_adapter.assertion_failed_error,
|
186
|
-
"in mock '#{@
|
187
|
+
"in mock '#{@flexmock_name}': #{ex.message}",
|
187
188
|
ex.backtrace
|
188
189
|
end
|
189
190
|
|
@@ -10,34 +10,12 @@
|
|
10
10
|
#+++
|
11
11
|
|
12
12
|
require 'flexmock/noop'
|
13
|
+
require 'flexmock/mock_container'
|
13
14
|
|
14
15
|
class FlexMock
|
15
16
|
class << self
|
16
17
|
attr_reader :framework_adapter
|
17
18
|
|
18
|
-
# :call-seq:
|
19
|
-
# should_receive(args) { |symbol| ... }
|
20
|
-
#
|
21
|
-
# This method provides common handling for the various should_receive
|
22
|
-
# argument lists. It sorts out the differences between symbols, arrays and
|
23
|
-
# hashes, and identifies the method names specified by each. As each
|
24
|
-
# method name is identified, create a mock expectation for it using the
|
25
|
-
# supplied block.
|
26
|
-
def should_receive(args) # :nodoc:
|
27
|
-
result = CompositeExpectation.new
|
28
|
-
args.each do |arg|
|
29
|
-
case arg
|
30
|
-
when Hash
|
31
|
-
arg.each do |k,v|
|
32
|
-
result.add(yield(k.to_sym).and_return(v))
|
33
|
-
end
|
34
|
-
when Symbol, String
|
35
|
-
result.add(yield(arg.to_sym))
|
36
|
-
end
|
37
|
-
end
|
38
|
-
result
|
39
|
-
end
|
40
|
-
|
41
19
|
# Class method to make sure that verify is called at the end of a
|
42
20
|
# test. One mock object will be created for each name given to
|
43
21
|
# the use method. The mocks will be passed to the block as
|
@@ -60,16 +38,14 @@ class FlexMock
|
|
60
38
|
#
|
61
39
|
def use(*names)
|
62
40
|
names = ["unknown"] if names.empty?
|
63
|
-
|
64
|
-
mocks = names.collect { |n|
|
41
|
+
container = UseContainer.new
|
42
|
+
mocks = names.collect { |n| container.flexmock(n) }
|
65
43
|
yield(*mocks)
|
66
44
|
rescue Exception => ex
|
67
|
-
got_exception = true
|
45
|
+
container.got_exception = true
|
68
46
|
raise
|
69
47
|
ensure
|
70
|
-
|
71
|
-
mock.mock_verify unless got_exception
|
72
|
-
end
|
48
|
+
container.flexmock_teardown
|
73
49
|
end
|
74
50
|
|
75
51
|
# Class method to format a method name and argument list as a nice
|
@@ -87,6 +63,21 @@ class FlexMock
|
|
87
63
|
def check(msg, &block) # :nodoc:
|
88
64
|
FlexMock.framework_adapter.assert_block(msg, &block)
|
89
65
|
end
|
66
|
+
|
90
67
|
end
|
91
68
|
|
92
|
-
|
69
|
+
# Container object to be used by the FlexMock.use method.
|
70
|
+
class UseContainer
|
71
|
+
include MockContainer
|
72
|
+
|
73
|
+
attr_accessor :got_exception
|
74
|
+
|
75
|
+
def initialize
|
76
|
+
@got_exception = false
|
77
|
+
end
|
78
|
+
|
79
|
+
def passed?
|
80
|
+
! got_exception
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
#---
|
4
|
+
# Copyright 2003, 2004, 2005, 2006, 2007 by Jim Weirich (jim@weirichhouse.org).
|
5
|
+
# All rights reserved.
|
6
|
+
#
|
7
|
+
# Permission is granted for use, copying, modification, distribution,
|
8
|
+
# and distribution of modified versions of this work as long as the
|
9
|
+
# above copyright notice is included.
|
10
|
+
#+++
|
11
|
+
|
12
|
+
|
13
|
+
class Module
|
14
|
+
def flexmock_deprecate(*method_names)
|
15
|
+
method_names.each do |method_name|
|
16
|
+
eval_line = __LINE__ + 1
|
17
|
+
module_eval %{
|
18
|
+
def #{method_name}(*args)
|
19
|
+
$stderr.puts "#{method_name} is deprecated, use flex#{method_name} instead"
|
20
|
+
flex#{method_name}(*args)
|
21
|
+
end
|
22
|
+
}, __FILE__, eval_line
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
# Deprecated Methods
|
28
|
+
# ==================
|
29
|
+
#
|
30
|
+
# The following methods are no longer supported in FlexMock. Include
|
31
|
+
# this file for legacy applications.
|
32
|
+
#
|
33
|
+
class FlexMock
|
34
|
+
|
35
|
+
# Handle all messages denoted by +sym+ by calling the given block
|
36
|
+
# and passing any parameters to the block. If we know exactly how
|
37
|
+
# many calls are to be made to a particular method, we may check
|
38
|
+
# that by passing in the number of expected calls as a second
|
39
|
+
# paramter.
|
40
|
+
def mock_handle(sym, expected_count=nil, &block) # :nodoc:
|
41
|
+
$stderr.puts "mock_handle is deprecated, use the new should_receive interface instead."
|
42
|
+
self.should_receive(sym).times(expected_count).returns(&block)
|
43
|
+
end
|
44
|
+
|
45
|
+
flexmock_deprecate :mock_verify, :mock_teardown, :mock_wrap
|
46
|
+
|
47
|
+
class PartialMockProxy
|
48
|
+
|
49
|
+
MOCK_METHODS << :any_instance
|
50
|
+
|
51
|
+
# any_instance is present for backwards compatibility with version 0.5.0.
|
52
|
+
# @deprecated
|
53
|
+
def any_instance(&block)
|
54
|
+
$stderr.puts "any_instance is deprecated, use new_instances instead."
|
55
|
+
new_instances(&block)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
module Ordering
|
60
|
+
flexmock_deprecate :mock_allocate_order, :mock_groups, :mock_current_order, :mock_validate_order
|
61
|
+
end
|
62
|
+
end
|
data/lib/flexmock/expectation.rb
CHANGED
@@ -39,8 +39,11 @@ class FlexMock
|
|
39
39
|
@count_validator_class = ExactCountValidator
|
40
40
|
@actual_count = 0
|
41
41
|
@return_value = nil
|
42
|
-
@
|
42
|
+
@return_queue = []
|
43
|
+
@yield_queue = []
|
43
44
|
@order_number = nil
|
45
|
+
@global_order_number = nil
|
46
|
+
@globally = nil
|
44
47
|
end
|
45
48
|
|
46
49
|
def to_s
|
@@ -52,9 +55,45 @@ class FlexMock
|
|
52
55
|
def verify_call(*args)
|
53
56
|
validate_order
|
54
57
|
@actual_count += 1
|
55
|
-
|
58
|
+
perform_yielding(args)
|
59
|
+
return_value(args)
|
56
60
|
end
|
57
61
|
|
62
|
+
# Public return value (odd name to avoid accidental use as a
|
63
|
+
# constraint).
|
64
|
+
def _return_value(args) # :nodoc:
|
65
|
+
return_value(args)
|
66
|
+
end
|
67
|
+
|
68
|
+
# Find the return value for this expectation. (private version)
|
69
|
+
def return_value(args)
|
70
|
+
case @return_queue.size
|
71
|
+
when 0
|
72
|
+
block = lambda { @return_value }
|
73
|
+
when 1
|
74
|
+
block = @return_queue.first
|
75
|
+
else
|
76
|
+
block = @return_queue.shift
|
77
|
+
end
|
78
|
+
block.call(*args)
|
79
|
+
end
|
80
|
+
private :return_value
|
81
|
+
|
82
|
+
# Yield stored values to any blocks given.
|
83
|
+
def perform_yielding(args)
|
84
|
+
@return_value = nil
|
85
|
+
unless @yield_queue.empty?
|
86
|
+
block = args.last
|
87
|
+
values = (@yield_queue.size == 1) ? @yield_queue.first : @yield_queue.shift
|
88
|
+
if block.respond_to?(:call)
|
89
|
+
@return_value = block.call(*values)
|
90
|
+
else
|
91
|
+
fail MockError, "No Block given to mock with 'and_yield' expectation"
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
private :perform_yielding
|
96
|
+
|
58
97
|
# Is this expectation eligible to be called again? It is eligible
|
59
98
|
# only if all of its count validators agree that it is eligible.
|
60
99
|
def eligible?
|
@@ -63,18 +102,18 @@ class FlexMock
|
|
63
102
|
|
64
103
|
# Validate that the order
|
65
104
|
def validate_order
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
105
|
+
if @order_number
|
106
|
+
@mock.flexmock_validate_order(to_s, @order_number)
|
107
|
+
end
|
108
|
+
if @global_order_number
|
109
|
+
@mock.flexmock_container.flexmock_validate_order(to_s, @global_order_number)
|
110
|
+
end
|
72
111
|
end
|
73
112
|
private :validate_order
|
74
113
|
|
75
114
|
# Validate the correct number of calls have been made. Called by
|
76
115
|
# the teardown process.
|
77
|
-
def
|
116
|
+
def flexmock_verify
|
78
117
|
@count_validators.each do |v|
|
79
118
|
v.validate(@actual_count)
|
80
119
|
end
|
@@ -142,16 +181,22 @@ class FlexMock
|
|
142
181
|
# +returns+ is an alias for +and_return+.
|
143
182
|
#
|
144
183
|
def and_return(*args, &block)
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
lambda {
|
184
|
+
if block_given?
|
185
|
+
@return_queue << block
|
186
|
+
else
|
187
|
+
args.each do |arg|
|
188
|
+
@return_queue << lambda { arg }
|
150
189
|
end
|
190
|
+
end
|
151
191
|
self
|
152
192
|
end
|
153
193
|
alias :returns :and_return # :nodoc:
|
154
194
|
|
195
|
+
def and_yield(*yield_values)
|
196
|
+
@yield_queue << yield_values
|
197
|
+
end
|
198
|
+
alias :yields :and_yield
|
199
|
+
|
155
200
|
|
156
201
|
# :call-seq:
|
157
202
|
# and_raise(an_exception)
|
@@ -169,13 +214,27 @@ class FlexMock
|
|
169
214
|
# additional arguments in the argument list will be passed to
|
170
215
|
# the +new+ constructor when it is invoked.
|
171
216
|
#
|
172
|
-
# +raises+ is an alias for +
|
217
|
+
# +raises+ is an alias for +and_raise+.
|
173
218
|
#
|
174
219
|
def and_raise(exception, *args)
|
175
220
|
and_return { raise exception, *args }
|
176
221
|
end
|
177
222
|
alias :raises :and_raise
|
178
223
|
|
224
|
+
# :call-seq:
|
225
|
+
# and_throw(a_symbol)
|
226
|
+
# and_throw(a_symbol, value)
|
227
|
+
#
|
228
|
+
# Declares that the method will throw the given symbol (with an
|
229
|
+
# optional value) when executed.
|
230
|
+
#
|
231
|
+
# +throws+ is an alias for +and_throw+.
|
232
|
+
#
|
233
|
+
def and_throw(sym, value=nil)
|
234
|
+
and_return { throw sym, value }
|
235
|
+
end
|
236
|
+
alias :throws :and_throw
|
237
|
+
|
179
238
|
# Declare that the method may be called any number of times.
|
180
239
|
def zero_or_more_times
|
181
240
|
at_least.never
|
@@ -262,16 +321,37 @@ class FlexMock
|
|
262
321
|
# m.should_receive(:end).ordered
|
263
322
|
#
|
264
323
|
def ordered(group_name=nil)
|
265
|
-
if
|
266
|
-
@
|
267
|
-
elsif (num = @mock.mock_groups[group_name])
|
268
|
-
@order_number = num
|
324
|
+
if @globally
|
325
|
+
@global_order_number = define_ordered(group_name, @mock.flexmock_container)
|
269
326
|
else
|
270
|
-
@order_number = @mock
|
271
|
-
@mock.mock_groups[group_name] = @order_number
|
327
|
+
@order_number = define_ordered(group_name, @mock)
|
272
328
|
end
|
329
|
+
@globally = false
|
273
330
|
self
|
274
331
|
end
|
332
|
+
|
333
|
+
# Modifier that changes the next ordered constraint to apply
|
334
|
+
# globally across all mock objects in the container.
|
335
|
+
def globally
|
336
|
+
@globally = true
|
337
|
+
self
|
338
|
+
end
|
339
|
+
|
340
|
+
# Helper method for defining ordered expectations.
|
341
|
+
def define_ordered(group_name, ordering)
|
342
|
+
fail UsageError, "Mock #{@mock.flexmock_name} is not in a container and cannot be globally ordered." if ordering.nil?
|
343
|
+
if group_name.nil?
|
344
|
+
result = ordering.flexmock_allocate_order
|
345
|
+
elsif (num = ordering.flexmock_groups[group_name])
|
346
|
+
result = num
|
347
|
+
else
|
348
|
+
result = ordering.flexmock_allocate_order
|
349
|
+
ordering.flexmock_groups[group_name] = result
|
350
|
+
end
|
351
|
+
result
|
352
|
+
end
|
353
|
+
private :define_ordered
|
354
|
+
|
275
355
|
end
|
276
356
|
|
277
357
|
##########################################################################
|