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