我有以下代码:
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")
#...
并遵循以下规范:
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
我得到以下输出:
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
方法以某种方式阻止中止占据一席之地。如何修复规范以检查应用程序是否已中止并具有特定消息?
答案 0 :(得分:4)
你的两个期望需要被视为单独的事物。首先,正如您所注意到的那样,abort
现在已经存根,因此实际上并没有中止代码的执行 - 现在它实际上就像puts
语句一样。因此,中止被调用两次:一次是您的预期消息,然后是begin
块内。如果你在预期结束时添加{ abort }
,它实际上会中止,但这也会中止你的测试套件。
你应该做的是使用lambda并确保调用abort
:
lambda { Rgc::Init.new({}, {}, []) }.should raise_error SystemExit
abort
将您提供的消息打印到stderr。要捕获它,您可以添加一个帮助程序来暂时用StringIO
对象替换stderr,然后您可以检查以下内容:
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
(感谢https://stackoverflow.com/a/11349621/424300替换stderr)