Browse files

Experiment with blocks for sequences.

- This design direction could easily cope with nested sequence blocks,
  but would that even be useful.
- Unfortunate that this solution increases coupling between Mock &
  Mockery.
- Need to decide separately whether it's useful to do lazy instantiation
  of sequences or have explicit sequence objects. Or perhaps both with
  the ability to lookup the ones lazily instantiated.
  • Loading branch information...
1 parent 1880ac4 commit 497f5de009332c1a930d20f11871e83e27b7bad9 @floehopper floehopper committed Feb 1, 2012
Showing with 53 additions and 3 deletions.
  1. +7 −1 lib/mocha/api.rb
  2. +7 −1 lib/mocha/mock.rb
  3. +9 −1 lib/mocha/mockery.rb
  4. +30 −0 test/acceptance/sequence_test.rb
View
8 lib/mocha/api.rb
@@ -122,7 +122,13 @@ def stub_everything(*arguments, &block)
def sequence(name)
Sequence.new(name)
end
-
+
+ def in_sequence(name, &block)
+ Mockery.instance.current_sequences.push(sequence(name))
+ yield
+ Mockery.instance.current_sequences.pop
+ end
+
# :call-seq: states(name) -> state_machine
#
# Returns a new +state_machine+ that is used to constrain the order in which expectations can occur.
View
8 lib/mocha/mock.rb
@@ -6,6 +6,7 @@
require 'mocha/parameters_matcher'
require 'mocha/unexpected_invocation'
require 'mocha/argument_iterator'
+require 'mocha/mockery'
module Mocha # :nodoc:
@@ -45,6 +46,9 @@ def expects(method_name_or_hash, backtrace = nil)
ensure_method_not_already_defined(method_name)
expectation = Expectation.new(self, method_name, backtrace)
expectation.returns(args.shift) if args.length > 0
+ if current_sequence = Mockery.instance.current_sequence
+ expectation.in_sequence(current_sequence)
+ end
@expectations.add(expectation)
}
end
@@ -78,6 +82,9 @@ def stubs(method_name_or_hash, backtrace = nil)
expectation = Expectation.new(self, method_name, backtrace)
expectation.at_least(0)
expectation.returns(args.shift) if args.length > 0
+ if current_sequence = Mockery.instance.current_sequence
+ expectation.in_sequence(current_sequence)
+ end
@expectations.add(expectation)
}
end
@@ -163,7 +170,6 @@ def method_missing(symbol, *arguments, &block)
if (matching_expectation = @expectations.match(symbol, *arguments)) || (!matching_expectation && !@everything_stubbed)
matching_expectation.invoke(&block) if matching_expectation
message = UnexpectedInvocation.new(self, symbol, *arguments).to_s
- require 'mocha/mockery'
message << Mockery.instance.mocha_inspect
raise ExpectationError.new(message, caller)
end
View
10 lib/mocha/mockery.rb
@@ -77,7 +77,15 @@ def mocks
def state_machines
@state_machines ||= []
end
-
+
+ def current_sequence
+ current_sequences.last
+ end
+
+ def current_sequences
+ @current_sequences ||= []
+ end
+
def mocha_inspect
message = ""
message << "unsatisfied expectations:\n- #{unsatisfied_expectations.map { |e| e.mocha_inspect }.join("\n- ")}\n" unless unsatisfied_expectations.empty?
View
30 test/acceptance/sequence_test.rb
@@ -189,4 +189,34 @@ def test_should_have_shortcut_for_expectations_to_be_in_more_than_one_sequence
assert_match Regexp.new("in sequence 'two'"), test_result.failures.first.message
end
+ def test_should_constrain_invocations_to_occur_in_expected_order_using_sequence_block
+ test_result = run_as_test do
+ mock = mock()
+
+ in_sequence('one') do
+ mock.expects(:first)
+ mock.expects(:second)
+ end
+
+ mock.second
+ mock.first
+ end
+ assert_failed(test_result)
+ end
+
+ def test_should_allow_invocations_in_sequence
+ test_result = run_as_test do
+ mock = mock()
+
+ in_sequence('one') do
+ mock.expects(:first)
+ mock.expects(:second)
+ end
+
+ mock.first
+ mock.second
+ end
+ assert_passed(test_result)
+ end
+
end

0 comments on commit 497f5de

Please sign in to comment.