Question

I have following code:

class Init
  def initialize(global_options, options, args)
    abort "Key file must be given!" if (key_file = args.first).nil?

    begin
      @secret = File.read(key_file)
    rescue
      abort "Cannot read key file #{key_file}"
    end

    stdout, stderr, status = Open3.capture3("git status  -uno --porcelain")
    #...

and following specs for it:

describe Rgc::Init do
  context :initialize do
    it 'should abort when no key file given' do
      Rgc::Init.any_instance.should_receive(:abort)
        .with("Key file must be given!")

      Rgc::Init.new({}, {}, [])
    end
  end
end

And I get following output:

Failure/Error: Rgc::Init.new({}, {}, [])
#<Rgc::Init:0x0000000157f728> received :abort with unexpected arguments
expected: ("Key file must be given!")
got: ("Cannot read key file ")

should_receive method somehow block abort to take a place. How to fix the spec to check that app has been aborted and with specific message?

Was it helpful?

Solution

Your two expectations need to be treated as separate things. First, as you noticed, abort is now stubbed and therefore doesn't actually abort execution of your code -- it's really just acting like a puts statement now. Because of this, abort is being called twice: once with your expected message, and then again within your begin block. And if you add { abort } to the end of your expectation, it will actually abort, but that will also abort your test suite.

What you should do is use a lambda and make sure the abort is called:

lambda { Rgc::Init.new({}, {}, []) }.should raise_error SystemExit

abort prints the message you give it to stderr. To capture that, you can add a helper to temporarily replace stderr with a StringIO object, which you can then check the contents of:

def capture_stderr(&block)
  original_stderr = $stderr
  $stderr = fake = StringIO.new
  begin
    yield
  ensure
    $stderr = original_stderr
  end
  fake.string
end

it 'should abort when no key file given' do
  stderr = capture_stderr do
    lambda { Rgc::Init.new({}, {}, []) }.should raise_error SystemExit
  end
  stderr.should == "Key file must be given!\n"
end

(Credit to https://stackoverflow.com/a/11349621/424300 for the stderr replacement)

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top