flexmock 0.6.4 → 0.7.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
##########################################################################
|