flexmock 1.3.2 → 1.3.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.
- checksums.yaml +7 -0
- data/Gemfile.lock +9 -9
- data/Rakefile +3 -1
- data/lib/flexmock.rb +1 -1
- data/lib/flexmock/argument_matchers.rb +1 -1
- data/lib/flexmock/argument_types.rb +1 -2
- data/lib/flexmock/base.rb +2 -1
- data/lib/flexmock/call_record.rb +30 -0
- data/lib/flexmock/call_validator.rb +68 -0
- data/lib/flexmock/composite_expectation.rb +56 -0
- data/lib/flexmock/core.rb +30 -64
- data/lib/flexmock/core_class_methods.rb +1 -1
- data/lib/flexmock/default_framework_adapter.rb +1 -1
- data/lib/flexmock/deprecated_methods.rb +8 -3
- data/lib/flexmock/errors.rb +1 -1
- data/lib/flexmock/expectation.rb +7 -84
- data/lib/flexmock/expectation_builder.rb +133 -0
- data/lib/flexmock/expectation_director.rb +6 -4
- data/lib/flexmock/expectation_recorder.rb +42 -0
- data/lib/flexmock/extensions/active_record_model.rb +109 -0
- data/lib/flexmock/mock_builder.rb +139 -0
- data/lib/flexmock/mock_container.rb +13 -214
- data/lib/flexmock/noop.rb +1 -1
- data/lib/flexmock/ordering.rb +1 -2
- data/lib/flexmock/partial_mock.rb +95 -57
- data/lib/flexmock/rails.rb +1 -1
- data/lib/flexmock/recorder.rb +4 -3
- data/lib/flexmock/rspec.rb +1 -1
- data/lib/flexmock/rspec_spy_matcher.rb +4 -0
- data/lib/flexmock/spy_describers.rb +22 -5
- data/lib/flexmock/test_unit.rb +2 -40
- data/lib/flexmock/test_unit_integration.rb +4 -4
- data/lib/flexmock/test_unit_testcase_extensions.rb +49 -0
- data/lib/flexmock/undefined.rb +1 -1
- data/lib/flexmock/validators.rb +18 -12
- data/lib/flexmock/version.rb +1 -1
- data/test/based_partials_test.rb +1 -1
- data/test/container_methods_test.rb +1 -1
- data/test/default_framework_adapter_test.rb +1 -1
- data/test/demeter_mocking_test.rb +52 -2
- data/test/deprecated_methods_test.rb +1 -1
- data/test/examples_from_readme_test.rb +1 -1
- data/test/expectation_description_test.rb +1 -1
- data/test/extended_should_receive_test.rb +1 -1
- data/test/mock_builder_test.rb +68 -0
- data/test/naming_test.rb +1 -1
- data/test/new_instances_test.rb +1 -1
- data/test/partial_mock_test.rb +23 -6
- data/test/record_mode_test.rb +1 -1
- data/test/rspec_integration/integration_spec.rb +1 -1
- data/test/samples_test.rb +1 -2
- data/test/should_ignore_missing_test.rb +1 -1
- data/test/should_receive_test.rb +1 -1
- data/test/test_setup.rb +17 -0
- data/test/test_unit_integration/auto_test_unit_test.rb +1 -1
- data/test/tu_integration_test.rb +1 -1
- data/test/undefined_test.rb +1 -1
- metadata +52 -52
- data/TAGS +0 -1056
- data/lib/flexmock/composite.rb +0 -10
- data/lib/flexmock/rails/view_mocking.rb +0 -144
- data/test/rails_view_stub_test.rb +0 -145
data/lib/flexmock/errors.rb
CHANGED
data/lib/flexmock/expectation.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
3
|
#---
|
4
|
-
# Copyright 2003-
|
4
|
+
# Copyright 2003-2013 by Jim Weirich (jim.weirich@gmail.com).
|
5
5
|
# All rights reserved.
|
6
6
|
|
7
7
|
# Permission is granted for use, copying, modification, distribution,
|
@@ -11,10 +11,10 @@
|
|
11
11
|
|
12
12
|
require 'flexmock/noop'
|
13
13
|
require 'flexmock/argument_matching'
|
14
|
+
require 'flexmock/expectation_recorder'
|
14
15
|
|
15
16
|
class FlexMock
|
16
17
|
|
17
|
-
####################################################################
|
18
18
|
# An Expectation is returned from each +should_receive+ message sent
|
19
19
|
# to mock object. Each expectation records how a message matching
|
20
20
|
# the message name (argument to +should_receive+) and the argument
|
@@ -386,7 +386,11 @@ class FlexMock
|
|
386
386
|
|
387
387
|
# Helper method for defining ordered expectations.
|
388
388
|
def define_ordered(group_name, ordering)
|
389
|
-
|
389
|
+
if ordering.nil?
|
390
|
+
fail UsageError,
|
391
|
+
"Mock #{@mock.flexmock_name} " +
|
392
|
+
"is not in a container and cannot be globally ordered."
|
393
|
+
end
|
390
394
|
if group_name.nil?
|
391
395
|
result = ordering.flexmock_allocate_order
|
392
396
|
elsif (num = ordering.flexmock_groups[group_name])
|
@@ -419,85 +423,4 @@ class FlexMock
|
|
419
423
|
|
420
424
|
end
|
421
425
|
|
422
|
-
##########################################################################
|
423
|
-
# A composite expectation allows several expectations to be grouped into a
|
424
|
-
# single composite and then apply the same constraints to all expectations
|
425
|
-
# in the group.
|
426
|
-
class CompositeExpectation
|
427
|
-
|
428
|
-
# Initialize the composite expectation.
|
429
|
-
def initialize
|
430
|
-
@expectations = []
|
431
|
-
end
|
432
|
-
|
433
|
-
# Add an expectation to the composite.
|
434
|
-
def add(expectation)
|
435
|
-
@expectations << expectation
|
436
|
-
end
|
437
|
-
|
438
|
-
# Apply the constraint method to all expectations in the composite.
|
439
|
-
def method_missing(sym, *args, &block)
|
440
|
-
@expectations.each do |expectation|
|
441
|
-
expectation.send(sym, *args, &block)
|
442
|
-
end
|
443
|
-
self
|
444
|
-
end
|
445
|
-
|
446
|
-
# The following methods return a value, so we make an arbitrary choice
|
447
|
-
# and return the value for the first expectation in the composite.
|
448
|
-
|
449
|
-
# Return the order number of the first expectation in the list.
|
450
|
-
def order_number
|
451
|
-
@expectations.first.order_number
|
452
|
-
end
|
453
|
-
|
454
|
-
# Return the associated mock object.
|
455
|
-
def mock
|
456
|
-
@expectations.first.mock
|
457
|
-
end
|
458
|
-
|
459
|
-
# Start a new method expectation. The following constraints will be
|
460
|
-
# applied to the new expectation.
|
461
|
-
def should_receive(*args, &block)
|
462
|
-
@expectations.first.mock.flexmock_define_expectation(caller.first, *args, &block)
|
463
|
-
end
|
464
|
-
|
465
|
-
# Return a string representations
|
466
|
-
def to_s
|
467
|
-
if @expectations.size > 1
|
468
|
-
"[" + @expectations.collect { |e| e.to_s }.join(', ') + "]"
|
469
|
-
else
|
470
|
-
@expectations.first.to_s
|
471
|
-
end
|
472
|
-
end
|
473
|
-
end
|
474
|
-
|
475
|
-
##########################################################################
|
476
|
-
# An expectation recorder records any expectations received and plays them
|
477
|
-
# back on demand. This is used to collect the expectations in the blockless
|
478
|
-
# version of the new_instances call.
|
479
|
-
#
|
480
|
-
class ExpectationRecorder
|
481
|
-
|
482
|
-
# Initialize the recorder.
|
483
|
-
def initialize
|
484
|
-
@expectations = []
|
485
|
-
end
|
486
|
-
|
487
|
-
# Save any incoming messages to be played back later.
|
488
|
-
def method_missing(sym, *args, &block)
|
489
|
-
@expectations << [sym, args, block]
|
490
|
-
self
|
491
|
-
end
|
492
|
-
|
493
|
-
# Apply the recorded messages to the given object in a chaining fashion
|
494
|
-
# (i.e. the result of the previous call is used as the target of the next
|
495
|
-
# call).
|
496
|
-
def apply(mock)
|
497
|
-
obj = mock
|
498
|
-
@expectations.each do |sym, args, block|
|
499
|
-
obj = obj.send(sym, *args, &block)
|
500
|
-
end
|
501
|
-
end
|
502
|
-
end
|
503
426
|
end
|
@@ -0,0 +1,133 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
#---
|
4
|
+
# Copyright 2003-2013 by Jim Weirich (jim.weirich@gmail.com).
|
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
|
+
require 'flexmock/composite_expectation'
|
13
|
+
|
14
|
+
class FlexMock
|
15
|
+
|
16
|
+
class ExpectationBuilder
|
17
|
+
# :call-seq:
|
18
|
+
# parse_should_args(args) { |symbol| ... }
|
19
|
+
#
|
20
|
+
# This method provides common handling for the various should_receive
|
21
|
+
# argument lists. It sorts out the differences between symbols, arrays and
|
22
|
+
# hashes, and identifies the method names specified by each. As each
|
23
|
+
# method name is identified, create a mock expectation for it using the
|
24
|
+
# supplied block.
|
25
|
+
def parse_should_args(mock, args, &block) # :nodoc:
|
26
|
+
result = CompositeExpectation.new
|
27
|
+
args.each do |arg|
|
28
|
+
case arg
|
29
|
+
when Hash
|
30
|
+
arg.each do |k,v|
|
31
|
+
exp = create_expectation(mock, k, &block).and_return(v)
|
32
|
+
result.add(exp)
|
33
|
+
end
|
34
|
+
when Symbol, String
|
35
|
+
result.add(create_expectation(mock, arg, &block))
|
36
|
+
end
|
37
|
+
end
|
38
|
+
result
|
39
|
+
end
|
40
|
+
|
41
|
+
# Create an expectation for the name on this mock. For simple
|
42
|
+
# mocks, this is done by calling the provided block parameter and
|
43
|
+
# letting the calling site handle the creation of the expectation
|
44
|
+
# (which differs between full mocks and partial mocks).
|
45
|
+
#
|
46
|
+
# If the name_chain contains demeter mocking chains, then the
|
47
|
+
# process is more complex. A series of mocks are created, each
|
48
|
+
# component of the chain returning the next mock until the
|
49
|
+
# expectation for the last component is returned.
|
50
|
+
def create_expectation(mock, name_chain, &block)
|
51
|
+
names = name_chain.to_s.split('.').map { |n| n.to_sym }
|
52
|
+
check_method_names(names)
|
53
|
+
if names.size == 1
|
54
|
+
block.call(names.first)
|
55
|
+
elsif names.size > 1
|
56
|
+
create_demeter_chain(mock, names)
|
57
|
+
else
|
58
|
+
fail "Empty list of names"
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
# Build the chain of mocks for demeter style mocking.
|
63
|
+
#
|
64
|
+
# This method builds a chain of mocks to support demeter style
|
65
|
+
# mocking. Given a mock chain of "first.second.third.last", we
|
66
|
+
# must build a chain of mock methods that return the next mock in
|
67
|
+
# the chain. The expectation for the last method of the chain is
|
68
|
+
# returned as the result of the method.
|
69
|
+
#
|
70
|
+
# Things to consider:
|
71
|
+
#
|
72
|
+
# * The expectations for all methods but the last in the chain
|
73
|
+
# will be setup to expect no parameters and to return the next
|
74
|
+
# mock in the chain.
|
75
|
+
#
|
76
|
+
# * It could very well be the case that several demeter chains
|
77
|
+
# will be defined on a single mock object, and those chains
|
78
|
+
# could share some of the same methods (e.g. "mock.one.two.read"
|
79
|
+
# and "mock.one.two.write" both share the methods "one" and
|
80
|
+
# "two"). It is important that the shared methods return the
|
81
|
+
# same mocks in both chains.
|
82
|
+
#
|
83
|
+
def create_demeter_chain(mock, names)
|
84
|
+
container = mock.flexmock_container
|
85
|
+
last_method = names.pop
|
86
|
+
names.each do |name|
|
87
|
+
exp = mock.flexmock_find_expectation(name)
|
88
|
+
if exp
|
89
|
+
next_mock = exp._return_value([])
|
90
|
+
check_proper_mock(next_mock, name)
|
91
|
+
else
|
92
|
+
next_mock = container.flexmock("demeter_#{name}")
|
93
|
+
mock.should_receive(name).and_return(next_mock)
|
94
|
+
end
|
95
|
+
mock = next_mock
|
96
|
+
end
|
97
|
+
mock.should_receive(last_method)
|
98
|
+
end
|
99
|
+
|
100
|
+
# Check that the given mock is a real FlexMock mock.
|
101
|
+
def check_proper_mock(mock, method_name)
|
102
|
+
unless mock.respond_to?(:should_receive)
|
103
|
+
fail FlexMock::UsageError,
|
104
|
+
"Conflicting mock declaration for '#{method_name}' in demeter style mock"
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
METHOD_NAME_ALTS = [
|
109
|
+
'[A-Za-z_][A-Za-z0-9_]*[=!?]?',
|
110
|
+
'\[\]=?',
|
111
|
+
'\*\\*',
|
112
|
+
'<<',
|
113
|
+
'>>',
|
114
|
+
'<=>',
|
115
|
+
'[<>=!]=',
|
116
|
+
'[=!]~',
|
117
|
+
'===',
|
118
|
+
'[-+]@',
|
119
|
+
'[-+\*\/%&^|<>~`!]'
|
120
|
+
].join("|")
|
121
|
+
METHOD_NAME_RE = /^(#{METHOD_NAME_ALTS})$/
|
122
|
+
|
123
|
+
# Check that all the names in the list are valid method names.
|
124
|
+
def check_method_names(names)
|
125
|
+
names.each do |name|
|
126
|
+
fail FlexMock::UsageError, "Ill-formed method name '#{name}'" if
|
127
|
+
name.to_s !~ METHOD_NAME_RE
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
EXP_BUILDER = ExpectationBuilder.new
|
133
|
+
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
3
|
#---
|
4
|
-
# Copyright 2003-
|
4
|
+
# Copyright 2003-2013 by Jim Weirich (jim.weirich@gmail.com).
|
5
5
|
# All rights reserved.
|
6
6
|
|
7
7
|
# Permission is granted for use, copying, modification, distribution,
|
@@ -13,7 +13,7 @@ require 'flexmock/noop'
|
|
13
13
|
require 'flexmock/errors'
|
14
14
|
|
15
15
|
class FlexMock
|
16
|
-
|
16
|
+
|
17
17
|
# The expectation director is responsible for routing calls to the
|
18
18
|
# correct expectations for a given argument list.
|
19
19
|
#
|
@@ -39,8 +39,10 @@ class FlexMock
|
|
39
39
|
exp = find_expectation(*args)
|
40
40
|
call_record.expectation = exp if call_record
|
41
41
|
FlexMock.check(
|
42
|
-
"no matching handler found for " +
|
43
|
-
|
42
|
+
"no matching handler found for " +
|
43
|
+
FlexMock.format_call(@sym, args)) { ! exp.nil? }
|
44
|
+
returned_value = exp.verify_call(*args)
|
45
|
+
returned_value
|
44
46
|
end
|
45
47
|
|
46
48
|
# Append an expectation to this director.
|
@@ -0,0 +1,42 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
#---
|
4
|
+
# Copyright 2003-2013 by Jim Weirich (jim.weirich@gmail.com).
|
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
|
+
class FlexMock
|
13
|
+
|
14
|
+
# An expectation recorder records any expectations received and plays them
|
15
|
+
# back on demand. This is used to collect the expectations in the blockless
|
16
|
+
# version of the new_instances call.
|
17
|
+
#
|
18
|
+
class ExpectationRecorder
|
19
|
+
|
20
|
+
# Initialize the recorder.
|
21
|
+
def initialize
|
22
|
+
@expectations = []
|
23
|
+
end
|
24
|
+
|
25
|
+
# Save any incoming messages to be played back later.
|
26
|
+
def method_missing(sym, *args, &block)
|
27
|
+
@expectations << [sym, args, block]
|
28
|
+
self
|
29
|
+
end
|
30
|
+
|
31
|
+
# Apply the recorded messages to the given object in a chaining fashion
|
32
|
+
# (i.e. the result of the previous call is used as the target of the next
|
33
|
+
# call).
|
34
|
+
def apply(mock)
|
35
|
+
obj = mock
|
36
|
+
@expectations.each do |sym, args, block|
|
37
|
+
obj = obj.send(sym, *args, &block)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
@@ -0,0 +1,109 @@
|
|
1
|
+
require 'flexmock/mock_container'
|
2
|
+
|
3
|
+
class FlexMock
|
4
|
+
module Extensions
|
5
|
+
|
6
|
+
class ActiveRecordModel
|
7
|
+
# Handle the argument list.
|
8
|
+
#
|
9
|
+
# This method is called whenever an unrecognized symbol is
|
10
|
+
# detected in the flexmock argument list. If the extension class
|
11
|
+
# can handle it, it should return true.
|
12
|
+
#
|
13
|
+
# Extension data can be stored in the opts.data hash for later use
|
14
|
+
# during the create and post_create phase.
|
15
|
+
def handle(args, opts)
|
16
|
+
return false unless args.first == :model
|
17
|
+
args.shift
|
18
|
+
opts.data[:model_class] = args.shift
|
19
|
+
opts.extended = self
|
20
|
+
true
|
21
|
+
end
|
22
|
+
|
23
|
+
# Create the test double.
|
24
|
+
#
|
25
|
+
# Create the custome test double according to the data from the
|
26
|
+
# argument list. The object returned from this method is the
|
27
|
+
# object returned from the original flexmock() method call. This
|
28
|
+
# the returned object is NOT the actual mock object (which is the
|
29
|
+
# case for things like partial proxies), then the opts.mock field
|
30
|
+
# should be set to contain the actual mock object.
|
31
|
+
def create(container, opts)
|
32
|
+
id = next_id
|
33
|
+
FlexMock.new("#{opts.data[:model_class]}_#{id}", container)
|
34
|
+
end
|
35
|
+
|
36
|
+
# Do any post-creation setup on the mock object.
|
37
|
+
def post_create(opts, location)
|
38
|
+
add_model_methods(opts.mock, opts.data[:model_class], location)
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
|
43
|
+
# Return the next id for mocked models.
|
44
|
+
def next_id
|
45
|
+
@id_counter ||= 10000
|
46
|
+
@id_counter += 1
|
47
|
+
end
|
48
|
+
|
49
|
+
def current_id
|
50
|
+
@id_counter
|
51
|
+
end
|
52
|
+
|
53
|
+
# Automatically add mocks for some common methods in ActiveRecord
|
54
|
+
# models.
|
55
|
+
def add_model_methods(mock, model_class, location)
|
56
|
+
add_model_methods_returning_values(mock, location,
|
57
|
+
[:id, current_id ],
|
58
|
+
[:to_params, current_id.to_s ],
|
59
|
+
[:new_record?, false ],
|
60
|
+
[:class, model_class ],
|
61
|
+
[:errors, make_mock_model_errors_for(mock, location) ])
|
62
|
+
|
63
|
+
add_model_methods_with_behavior(mock, location,
|
64
|
+
[:is_a?, lambda { |other| other == model_class } ],
|
65
|
+
[:instance_of?, lambda { |other| other == model_class } ],
|
66
|
+
[:kind_of?, lambda { |other| model_class.ancestors.include?(other) } ])
|
67
|
+
end
|
68
|
+
|
69
|
+
def add_model_methods_returning_values(mock, location, *pairs)
|
70
|
+
pairs.each do |method, retval|
|
71
|
+
make_default_behavior(mock, location, method, retval)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def add_model_methods_with_behavior(mock, location, *pairs)
|
76
|
+
pairs.each do |method, block|
|
77
|
+
make_default_behavior(mock, location, method, &block)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
# Create a mock model errors object (with default behavior).
|
82
|
+
def make_mock_model_errors_for(mock, location)
|
83
|
+
result = mock.flexmock_container.flexmock("errors")
|
84
|
+
make_default_behavior(result, location, :count, 0)
|
85
|
+
make_default_behavior(result, location, :full_messages, [])
|
86
|
+
result
|
87
|
+
end
|
88
|
+
|
89
|
+
# Define default behavior on a mock object.
|
90
|
+
#
|
91
|
+
# If a block is given, use that to define the behavior. Otherwise
|
92
|
+
# return the +retval+ value.
|
93
|
+
def make_default_behavior(mock, location, method, retval=nil, &block)
|
94
|
+
if block_given?
|
95
|
+
mock.flexmock_define_expectation(location, method).
|
96
|
+
with(FlexMock.any).
|
97
|
+
and_return(&block).
|
98
|
+
by_default
|
99
|
+
else
|
100
|
+
mock.flexmock_define_expectation(location, method).
|
101
|
+
and_return(retval).
|
102
|
+
by_default
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
FlexMock::CONTAINER_HELPER.add_extension(ActiveRecordModel.new)
|
108
|
+
end
|
109
|
+
end
|
@@ -0,0 +1,139 @@
|
|
1
|
+
class FlexMock
|
2
|
+
|
3
|
+
# This class contains helper methods for mock containers. Since
|
4
|
+
# MockContainer is a module that is designed to be mixed into other
|
5
|
+
# classes, (particularly testing framework test cases), we don't
|
6
|
+
# want to pollute the method namespace of the class that mixes in
|
7
|
+
# MockContainer. So we have aggressively moved a number of
|
8
|
+
# MockContainer methods out of that class and into
|
9
|
+
# MockBuilder to isoloate the names.
|
10
|
+
#
|
11
|
+
class MockBuilder
|
12
|
+
def initialize(container)
|
13
|
+
@container = container
|
14
|
+
end
|
15
|
+
|
16
|
+
def define_a_mock(location, *args, &block)
|
17
|
+
opts = parse_creation_args(args)
|
18
|
+
if opts.safe_mode && ! block_given?
|
19
|
+
raise UsageError, "a block is required in safe mode"
|
20
|
+
end
|
21
|
+
|
22
|
+
result = create_double(opts)
|
23
|
+
flexmock_mock_setup(opts.mock, opts, location, &block)
|
24
|
+
run_post_creation_hooks(opts, location)
|
25
|
+
result
|
26
|
+
end
|
27
|
+
|
28
|
+
FlexOpts = Struct.new(
|
29
|
+
:name, :defs, :safe_mode, :mock,
|
30
|
+
:domain_obj, :base_class,
|
31
|
+
:extended, :extended_data
|
32
|
+
) do
|
33
|
+
def data
|
34
|
+
self.extended_data ||= {}
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
# Parse the list of flexmock() arguments and populate the opts object.
|
39
|
+
def parse_creation_args(args)
|
40
|
+
opts = FlexOpts.new
|
41
|
+
while ! args.empty?
|
42
|
+
case args.first
|
43
|
+
when Symbol
|
44
|
+
unless parse_create_symbol(args, opts)
|
45
|
+
opts.name = args.shift.to_s
|
46
|
+
end
|
47
|
+
when String, Symbol
|
48
|
+
opts.name = args.shift.to_s
|
49
|
+
when Hash
|
50
|
+
opts.defs = args.shift
|
51
|
+
when FlexMock
|
52
|
+
opts.mock = args.shift
|
53
|
+
else
|
54
|
+
opts.domain_obj = args.shift
|
55
|
+
end
|
56
|
+
end
|
57
|
+
set_base_class(opts)
|
58
|
+
opts
|
59
|
+
end
|
60
|
+
|
61
|
+
# Create the test double based on the args options.
|
62
|
+
def create_double(opts)
|
63
|
+
if opts.extended
|
64
|
+
result = opts.extended.create(container, opts)
|
65
|
+
elsif opts.domain_obj
|
66
|
+
result = create_partial(opts)
|
67
|
+
else
|
68
|
+
result = create_mock(opts)
|
69
|
+
end
|
70
|
+
opts.mock ||= result
|
71
|
+
result
|
72
|
+
end
|
73
|
+
|
74
|
+
# Run any post creation hooks specified by an extension.
|
75
|
+
def run_post_creation_hooks(opts, location)
|
76
|
+
if opts.extended
|
77
|
+
opts.extended.post_create(opts, location)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
|
82
|
+
# Setup the test double with its expections and such.
|
83
|
+
def flexmock_mock_setup(mock, opts, location)
|
84
|
+
mock.flexmock_based_on(opts.base_class) if opts.base_class
|
85
|
+
mock.flexmock_define_expectation(location, opts.defs)
|
86
|
+
yield(mock) if block_given?
|
87
|
+
container.flexmock_remember(mock)
|
88
|
+
end
|
89
|
+
|
90
|
+
attr_reader :container
|
91
|
+
private :container
|
92
|
+
|
93
|
+
private
|
94
|
+
|
95
|
+
# Set the base class if not defined and partials are based.
|
96
|
+
def set_base_class(opts)
|
97
|
+
if ! opts.base_class && opts.domain_obj && FlexMock.partials_are_based
|
98
|
+
opts.base_class = opts.domain_obj.class
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
# Handle a symbol in the flexmock() args list.
|
103
|
+
def parse_create_symbol(args, opts)
|
104
|
+
case args.first
|
105
|
+
when :base, :safe
|
106
|
+
opts.safe_mode = (args.shift == :safe)
|
107
|
+
opts.domain_obj = args.shift
|
108
|
+
when :on
|
109
|
+
args.shift
|
110
|
+
opts.base_class = args.shift
|
111
|
+
opts.name ||= "#{opts.base_class} Mock"
|
112
|
+
else
|
113
|
+
CONTAINER_HELPER.extensions.each do |ext|
|
114
|
+
handled = ext.handle(args, opts)
|
115
|
+
return true if handled
|
116
|
+
end
|
117
|
+
return false
|
118
|
+
end
|
119
|
+
true
|
120
|
+
end
|
121
|
+
|
122
|
+
# Create a mock object in the options.
|
123
|
+
def create_mock(opts)
|
124
|
+
opts.mock ||= FlexMock.new(opts.name || "unknown", container)
|
125
|
+
opts.mock
|
126
|
+
end
|
127
|
+
|
128
|
+
# Create a partial mock object in options.
|
129
|
+
def create_partial(opts)
|
130
|
+
opts.mock = PartialMockProxy.make_proxy_for(
|
131
|
+
opts.domain_obj,
|
132
|
+
container, opts.name,
|
133
|
+
opts.safe_mode)
|
134
|
+
opts.domain_obj
|
135
|
+
end
|
136
|
+
|
137
|
+
end
|
138
|
+
|
139
|
+
end
|