Skip to content

Instantly share code, notes, and snippets.

@lukeredpath
Created January 30, 2012 14:47
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save lukeredpath/1704783 to your computer and use it in GitHub Desktop.
Save lukeredpath/1704783 to your computer and use it in GitHub Desktop.
Rspec mock sequences?
# preferred format:
in_sequence(:task_order) do
task_one.should_receive(:execute)
task_two.should_receive(:execute)
end
# or even:
sequence = sequence(:task_order)
task_one.should_receive(:execute).in_sequence(sequence)
task_two.should_receive(:execute).in_sequence(sequence)
@foca
Copy link

foca commented Jan 30, 2012

This used to work with blocks:

task_one.should_receive(:execute) do
  task_two.should_receive(:execute)
end

Though I haven't tried this since forever, so YMMV :)

@lukeredpath
Copy link
Author

@foca hey, that worked, thanks. It's not pretty, but it will do the trick.

@lukeredpath
Copy link
Author

@dchelimsky does that work across different objects/mocks or only within the scope of a single receiver?

@dchelimsky
Copy link

Recollection is it works across objects, but the docs and specs don't say or specify that. Give it a whirl and let me know and I'll update the docs to answer that question.

@floehopper
Copy link

I assume you can still use Mocha with RSpec? Get your lovely sequences here ;-)

@dchelimsky
Copy link

@floehopper - the docs only show a single receiver - do they work across objects?

@floehopper
Copy link

Yes. I believe they do work across objects :-

require "test/unit"
require "mocha"

class FooTest < Test::Unit::TestCase
  def test_foo
    sequence = sequence(:task_order)
    task_one = mock("task_one")
    task_two = mock("task_two")

    task_one.expects(:execute).in_sequence(sequence)
    task_two.expects(:execute).in_sequence(sequence)

    task_one.execute
    task_two.execute
  end
end

I've added issue floehopper/mocha#59 to improve the examples in the docs. Thanks.

@dchelimsky
Copy link

Just tried it with both rspec and mocha and both do a less than desirable job. rspec doesn't enforce order across objects (so only mocha satisfies @lukeredpath's issue right now), but it's messaging is clear when order is violated within one object:

Failures:

  1) something does something
     Failure/Error: a.bar
       Double received :bar out of order
     # ./example_spec.rb:10:in `block (2 levels) in <top (required)>'

Mocha does enforce order across objects, but its messaging is unclear. Here's the result of the example with the last two lines reversed, e.g.

    task_one.expects(:execute).in_sequence(sequence)
    task_two.expects(:execute).in_sequence(sequence)

    task_one.execute
    task_two.execute
unexpected invocation: #<Mock:task_two>.execute()
unsatisfied expectations:
- expected exactly once, not yet invoked: #<Mock:task_one>.execute(any_parameters); in sequence :task_order
- expected exactly once, not yet invoked: #<Mock:task_two>.execute(any_parameters); in sequence :task_order

Looks like we both have some work to do :)

rspec/rspec-mocks#101
https://github.com/floehopper/mocha/issues/60

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment