2013-05-31 31 views
21

我有,其对猫模型和不正确的输入的情况下,一些动作的方法引发了一个异常:我该如何“期待”在RSpec中引发异常的东西?

context "hungry cat" do 
    it { expect { eat(what: nil) }.to raise_error } 
end 

我想要做的是检查是否这种方法改变猫的状态,这样的:

context "hungry cat" do 
    it { expect { eat(what: nil) }.to raise_error } 
    it { expect { eat(what: nil) }.not_to change(cat, :status) } 
end 

问题是,因为eat(what: nil)将引发异常,第二个it将失败,无论如何。那么,是否可以忽略异常并检查一些情况?

我知道这是可以做到这样的:

it do 
    expect do 
    begin 
     eat(what: nil) 
    rescue 
    end 
    end.not_to change(cat, :status) 
end 

但它的方式太丑陋了。

+2

“它{expect {eat(what:nil)rescue nil} .not_to change(cat,:status)}'? – awendt

+0

@awendt很好,你可以发布它作为答案? – Andrew

+0

在'Test/Unit'中,我认为有一个很好的断言,assert_raise。 –

回答

18

您可以使用 “救市无” 的成语,以缩短你已经拥有:

it { expect { eat(what: nil) rescue nil }.not_to change(cat, :status) } 
+4

这是有效的,但我希望有一种rspec的方式来做到这一点,例如:'expect {...} .ignoring_errors.to change(cat,:状态)' –

0

这听起来很奇怪,eat(what: nil)代码没有针对您的每个测试单独运行,并且影响其他测试。我不确定,但也许稍微重写测试将解决问题或更准确地确定问题的出处(在下面选择您的口味)。

使用should

context "hungry cat" do 
    context "when not given anything to eat" do 
    subject { -> { eat(what: nil) } } 
    it { should raise_error } 
    it { should_not change(cat, :status) } 
    end 
end 

使用expect

context "hungry cat" do 
    context "when not given anything to eat" do 
    let(:eating_nothing) { -> { eat(what: nil) } } 
    it "raises an error" do 
     expect(eating_nothing).to raise_error 
    end 
    it "doesn't change cat's status" do 
     expect(eating_nothing).to_not change(cat, :status) 
    end 
    end 
end 
+0

我想你误解了这个问题。如果“吃”引发异常,第二种情况将总是失败,因为例外情况不受限制。 – Andrew

+0

也许我做到了。您系统中的预期行为是否具有您的用户可能生成的未处理的异常?如果是这样,你能解释一下为什么,在这里或在编辑你的问题? –

+0

是的,它当然是期望的行为,而且大多数ruby库可以生成应该由用户处理的异常,并且应该测试这种行为。例如。在'读取文件'过程中'#save!','Float('aaa')',EOFError。在我的情况下,我想测试的是在抛出异常(事务回滚,描述符关闭等)后上下文已成功恢复。 – Andrew

12

在RSpec的3你可以将两个测试链接成一个。我发现这比rescue nil方法更具可读性。

it { expect { eat(what: nil) }.to raise_error.and not_to change(cat, :status)}

+4

你确定这是正确的语法吗?它给了我错误:'NoMethodError: 未定义的方法'not_to'为# dombesz

+1

没有这将无法正常工作,请参阅下面的注释。 –

11

您可以用chain积极and断言。如果你想在链中混合一个否定的,RSpec 3.1引入了define_negated_matcher

你可以这样做:

RSpec::Matchers.define_negated_matcher :avoid_changing, :change 

expect { eat(what: nil) } 
    .to raise_error 
    .and avoid_changing(cat, :status) 

通过this comment启发。

+1

这真的很棒谢谢你。不能相信我以前没有遇到过这种情况。 – adaam

+1

这应该是很好的答案! –

相关问题