ChatGPT解决这个技术问题 Extra ChatGPT

如何在 Rails/RSpec 中测试异常引发?

有以下代码:

def index
    @car_types = car_brand.car_types
end

def car_brand
    CarBrand.find(params[:car_brand_id])
    rescue ActiveRecord::RecordNotFound
        raise Errors::CarBrandNotFound.new 
end

我想通过 RSpec 对其进行测试。我的代码是:

it 'raises CarBrandNotFound exception' do
    get :index, car_brand_id: 0
    expect(response).to raise_error(Errors::CarBrandNotFound)
end

id 等于 0 的 CarBrand 不存在,因此我的控制器代码引发 Errors::CarBrandNotFound,但我的测试代码告诉我没有引发任何问题。我该如何解决?我错了什么?


G
Grzegorz

使用 expect{} 而不是 expect()

例子:

it do 
  expect { response }.to raise_error(Errors::CarBrandNotFound)
end

值得指出的是,这解决了这个问题,因为 {} 语法创建了一个块来监视要引发的给定异常。 MiniTest 在检查代码块是否引发异常时具有类似的语法要求。
我不敢相信。 1 小时的尝试,它只是将 ( ) 变成了 { }!太感谢了
我无法在 Rails 7 中使用此方法
J
Jakob S

为了规范错误处理,您需要在一个块上设置您的期望;评估对象不会引发错误。

所以你想做这样的事情:

expect {
  get :index, car_brand_id: 0
}.to raise_error(Errors::CarBrandNotFound)

有关详细信息,请参阅 Expect error

不过,我有点惊讶你没有得到任何异常冒泡到你的规范结果。


@jakob-s 您在此处使用的预期错误行为不适用于控制器请求。 get :index, car_brand_id: 0 本身不会引发错误。
@RicardoOtero 事情可能已经改变,但就其价值而言,它对我有用:gist.github.com/koppen/0e1d0894a908a3768847。但可以肯定的是,堆栈中的某些东西可能会在错误冒泡到规范运行器之前对其进行处理。
这是当前 rspec 版本的正确答案,应该投票赞成
那是对的。测试异常的正确形式是在 except 方法上使用 {} 而不是 ()。
B
BroiSatse

get :index 永远不会引发异常 - 它会像真实服务器那样将响应设置为 500 错误。

而是尝试:

it 'raises CarBrandNotFound exception' do
  controller.params[:car_brand_id] = 0
  expect{ controller.car_brand }.to raise_error(Errors::CarBrandNotFound)
end

我很高兴有人提到这一点! :) Jakob 试图教育他们,它永远不会在最受支持的答案中引发异常,但他面临着一些不正确的抵抗。 👍