Rails ActiveSupport: 如何断言错误已被引发?

60

我想测试我的模型中一个会抛出特定错误的函数。这个函数大致如下:

def merge(release_to_delete)
  raise "Can't merge a release with itself!" if( self.id == release_to_delete.id )
  raise "Can only merge releases by the same artist" if( self.artist != release_to_delete.artist   )
  #actual merge code here
end

现在我想进行一项断言,即当我使用导致这些异常的参数调用此函数时,确实会抛出异常。我查看了ActiveSupport文档,但没有找到有用的信息。你有什么建议吗?

2个回答

127

所以单元测试并不真正属于activesupport。Ruby自带了一个典型的xunit框架(在标准库中为Test::Unit 1.8.x版本中,为MiniTest 1.9版本中),而activesupport只是在其中添加了一些东西。

如果您正在使用Test::Unit/MiniTest

assert_raise(Exception) { whatever.merge }

如果你正在使用 rspec(不幸的是文档不太好,但更受欢迎)

lambda { whatever.merge }.should raise_error

如果您想要检查引发的异常

exception = assert_raises(Exception) { whatever.merge }
assert_equal( "message", exception.message )

8
谢谢!尽管需要使用RuntimeError而不是exception,就像这样:assert_raise( RuntimeError ){ artist1.merge(artist1) }这份指南非常有帮助:http://guides.rubyonrails.org/testing.html - spilliton
1
@spilliton:这是因为Ruby解释器将上面的代码视为assert_raise(Exception() { whatever.merge }),即它寻找一个名为Exception的方法,并使用给定的块调用它。添加括号可以消除歧义。(已经修正了答案) - Daniel Rikowski
在rspec 3中,使用expect { whatever.merge }.to raise_error(http://www.relishapp.com/rspec/rspec-expectations/v/3-1/docs/built-in-matchers/raise-error-matcher) - Jared Beck

17

为确保不会引发异常(或已成功处理异常),请在测试用例中执行以下操作:

assert_nothing_raised RuntimeError do
  whatever.merge
end

要检查是否触发了错误,请在测试用例中执行以下操作:

assert_raise RuntimeError do
  whatever.merge
end

提前告诉你,whatever.merge就是导致错误的代码(或不是,这取决于断言类型)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接