Rails / RSpec에서 예외 발생을 테스트하는 방법은 무엇입니까?


84

다음 코드가 있습니다.

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가 발생하지만 테스트 코드는 아무것도 발생하지 않았다고 알려줍니다. 어떻게 고칠 수 있습니까? 내가 뭘 잘못 했어?

답변:


115

오류 처리를 지정하려면 블록에 대한 기대치를 설정해야합니다. 객체를 평가해도 오류가 발생할 수 없습니다.

따라서 다음과 같이하고 싶습니다.

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

자세한 내용은 예상 오류 를 참조하세요.

그래도 사양 결과까지 예외가 발생하지 않는다는 사실에 약간 놀랐습니다.


1
@ jakob-s 여기서 사용하는 예상 오류 동작은 컨트롤러 요청에서 작동하지 않습니다. 그 get :index, car_brand_id: 0자체로는 오류가 발생하지 않습니다.
Ricardo Otero 2015 년

@RicardoOtero 상황이 변경되었을 수 있지만 그만한 가치는 gist.github.com/koppen/0e1d0894a908a3768847 입니다. 그러나 확실히 스택의 어떤 것이 스펙 러너에게 버블 링되기 전에 오류를 처리 할 수 ​​있습니다.
Jakob S

이렇게까지 투표를해야 현재의 RSpec에 버전 ANS에 대한 정답입니다
닐 우즈

맞아요. 예외를 테스트하는 올바른 형식은 except 메소드에서 () 대신 {}를 사용하는 것입니다.
Luiz Henrique

109

사용 expect{}대신에 expect().


7
{} 구문이 발생하는 주어진 예외를 모니터링 할 블록을 생성하기 때문에 이것이 문제를 해결한다는 점을 지적 할 가치가 있습니다. MiniTest에는 코드 블록에서 예외가 발생하는지 확인할 때 유사한 구문 요구 사항이 있습니다.
Argus9

1
이런 작은 변화. 나는 한동안 내 바퀴를 갈고 있었다. 감사합니다.
josh

4
믿을 수가 없어요. 노력하고 그냥 돌고 1 시간 ( ){ }! 정말 감사합니다
사이먼 프란 젠에게

1
그래, 나도
똑같아요

2
댓글을 써야한다는 것을 알고 있지만 ... 그래도 응답 해 주셔서 감사합니다. 여러 접근 방식을 거쳐 마침내 내 문제에 대한 해결책을 찾았습니다.
Florin Lei

18

get :index 예외를 발생시키지 않습니다. 실제 서버가하는 것처럼 응답을 500 오류로 설정합니다.

대신 다음을 시도하십시오.

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

1
누군가가 이것을 언급하게되어 기쁩니다! :) Jakob은 가장 많은 찬성 응답에서 예외가 발생하지 않을 것이라고 교육하려고했지만 잘못된 저항에 직면했습니다. 👍
Tarek N. Elsamni
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.