Class: FlexMock::ExpectationBuilder
- Defined in:
- lib/flexmock/expectation_builder.rb
Constant Summary collapse
- METHOD_NAME_ALTS =
[ '[A-Za-z_][A-Za-z0-9_]*[=!?]?', '\[\]=?', '\*\\*', '<<', '>>', '<=>', '[<>=!]=', '[=!]~', '===', '[-+]@', '[-+\*\/%&^|<>~`!]' ].join("|")
- METHOD_NAME_RE =
/^(#{METHOD_NAME_ALTS})$/
Instance Method Summary collapse
-
#check_method_names(names) ⇒ Object
Check that all the names in the list are valid method names.
-
#check_proper_mock(mock, method_name) ⇒ Object
Check that the given mock is a real FlexMock mock.
-
#create_demeter_chain(mock, names) ⇒ Object
Build the chain of mocks for demeter style mocking.
-
#create_expectation(mock, name_chain, &block) ⇒ Object
Create an expectation for the name on this mock.
-
#parse_should_args(mock, args, &block) ⇒ Object
:call-seq: parse_should_args(args) { |symbol| … }.
Instance Method Details
#check_method_names(names) ⇒ Object
Check that all the names in the list are valid method names.
124 125 126 127 128 129 |
# File 'lib/flexmock/expectation_builder.rb', line 124 def check_method_names(names) names.each do |name| fail FlexMock::UsageError, "Ill-formed method name '#{name}'" if name.to_s !~ METHOD_NAME_RE end end |
#check_proper_mock(mock, method_name) ⇒ Object
Check that the given mock is a real FlexMock mock.
101 102 103 104 105 106 |
# File 'lib/flexmock/expectation_builder.rb', line 101 def check_proper_mock(mock, method_name) unless mock.respond_to?(:should_receive) fail FlexMock::UsageError, "Conflicting mock declaration for '#{method_name}' in demeter style mock" end end |
#create_demeter_chain(mock, names) ⇒ Object
Build the chain of mocks for demeter style mocking.
This method builds a chain of mocks to support demeter style mocking. Given a mock chain of “first.second.third.last”, we must build a chain of mock methods that return the next mock in the chain. The expectation for the last method of the chain is returned as the result of the method.
Things to consider:
-
The expectations for all methods but the last in the chain will be setup to expect no parameters and to return the next mock in the chain.
-
It could very well be the case that several demeter chains will be defined on a single mock object, and those chains could share some of the same methods (e.g. “mock.one.two.read” and “mock.one.two.write” both share the methods “one” and “two”). It is important that the shared methods return the same mocks in both chains.
83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 |
# File 'lib/flexmock/expectation_builder.rb', line 83 def create_demeter_chain(mock, names) container = mock.flexmock_container last_method = names.pop names.each do |name| exp = mock.flexmock_find_expectation(name) if exp next_mock = exp._return_value([]) check_proper_mock(next_mock, name) else next_mock = container.flexmock("demeter_#{name}") mock.should_receive(name).and_return(next_mock) end mock = next_mock end mock.should_receive(last_method) end |
#create_expectation(mock, name_chain, &block) ⇒ Object
Create an expectation for the name on this mock. For simple mocks, this is done by calling the provided block parameter and letting the calling site handle the creation of the expectation (which differs between full mocks and partial mocks).
If the name_chain contains demeter mocking chains, then the process is more complex. A series of mocks are created, each component of the chain returning the next mock until the expectation for the last component is returned.
50 51 52 53 54 55 56 57 58 59 60 |
# File 'lib/flexmock/expectation_builder.rb', line 50 def create_expectation(mock, name_chain, &block) names = name_chain.to_s.split('.').map { |n| n.to_sym } check_method_names(names) if names.size == 1 block.call(names.first) elsif names.size > 1 create_demeter_chain(mock, names) else fail "Empty list of names" end end |
#parse_should_args(mock, args, &block) ⇒ Object
:call-seq:
parse_should_args(args) { |symbol| ... }
This method provides common handling for the various should_receive argument lists. It sorts out the differences between symbols, arrays and hashes, and identifies the method names specified by each. As each method name is identified, create a mock expectation for it using the supplied block.
25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
# File 'lib/flexmock/expectation_builder.rb', line 25 def parse_should_args(mock, args, &block) # :nodoc: result = CompositeExpectation.new args.each do |arg| case arg when Hash arg.each do |k,v| exp = create_expectation(mock, k, &block).and_return(v) result.add(exp) end when Symbol, String result.add(create_expectation(mock, arg, &block)) end end result end |