如何指定退出或中止的方法

我有一个从CLI触发的方法,它有一些明确退出或中止的逻辑路径。 我发现在为此方法编写规范时,RSpec将其标记为失败,因为退出是exception。 这是一个简单的例子:

def cli_method if condition puts "Everything's okay!" else puts "GTFO!" exit end end 

我可以使用should raise_error(SystemExit)将规范包装在lambda中,但是忽略了块内发生的任何断言。 要明确:我不是在测试退出本身,而是在它之前发生的逻辑。 我该如何选择这种方法呢?

只需将断言放在lambda之外,例如:

 class Foo attr_accessor :result def logic_and_exit @result = :bad_logic exit end end describe 'Foo#logic_and_exit' do before(:each) do @foo = Foo.new end it "should set @foo" do lambda { @foo.logic_and_exit; exit }.should raise_error SystemExit @foo.result.should == :logics end end 

当我运行rspec时,它正确告诉我:

 expected: :logics got: :bad_logic (using ==) 

有什么情况对你不起作用吗?

编辑:我在lambda中添加了一个’exit’调用来处理logic_and_exit没有退出的情况。

编辑2:更好的是,只需在测试中执行此操作:

 begin @foo.logic_and_exit rescue SystemExit end @foo.result.should == :logics 

覆盖Rspec 3期望语法的新答案。

测试输出

只是为了测试你真正想要的东西(即你没有测试exception或值响应),输出到STDOUT的是什么。

condition为假时

 it "has a false condition" do # NOTE: Set up your condition's parameters to make it false expect { begin cli_method rescue SystemExit end }.to output("GTFO").to_stdout # or .to_stderr end 

condition成立时

 it "has a true condition" do # NOTE: Set up your condition's parameters to make it true expect { begin cli_method rescue SystemExit end }.to output("Everything's okay!").to_stdout end 

请注意, output("String").to_...可以接受正则Regex例如。

 output(/^Everything's okay!$/).to_stdout 

它也可以从stderr捕获,例如。

 output("GTFO").to_stderr 

(对于OP的例子,这将是一个更好的发送它的地方。)

测试退出

您可以单独测试false条件也会引发SystemExit

 it "exits when condition is false" do # NOTE: Set up your condition's parameters to make it false expect{cli_method}.to raise_error SystemExit end it "doesn't exit when condition is true" do # NOTE: Set up your condition's parameters to make it true expect{cli_method}.not_to raise_error SystemExit end 

我可以使用raise_error(SystemExit)将规范包装在lambda中,但是忽略了块内发生的任何断言。

我认为将测试放在lambda内部或外部没有区别。 在任何一种情况下,失败消息都有点神秘:

 def cli_method(condition) if condition puts "OK" else puts "GTFO" exit end end describe "cli_method" do context "outside lambda" do # passing it "writes to STDOUT when condition is false" do STDOUT.should_receive(:puts).with("GTFO") lambda { cli_method(false) }.should raise_error(SystemExit) end # failing it "does not write to STDOUT when condition is false" do STDOUT.should_not_receive(:puts).with("GTFO") lambda { cli_method(false) }.should raise_error(SystemExit) end end context "inside lambda" do # passing it "writes to STDOUT when condition is false" do lambda { STDOUT.should_receive(:puts).with("GTFO") cli_method(false) }.should raise_error(SystemExit) end # failing it "does not write to STDOUT when condition is false" do lambda { STDOUT.should_not_receive(:puts).with("GTFO") cli_method(false) }.should raise_error(SystemExit) end end end # output .FF Failures: 1) cli_method outside lambda does not write to STDOUT when condition is false Failure/Error: lambda { expected SystemExit, got #).puts("GTFO") expected: 0 times received: 1 time> # ./gtfo_spec.rb:23:in `block (3 levels) in ' 2) cli_method inside lambda does not write to STDOUT when condition is false Failure/Error: lambda { expected SystemExit, got #).puts("GTFO") expected: 0 times received: 1 time> # ./gtfo_spec.rb:39:in `block (3 levels) in '