Come testare il sollevamento di eccezioni in Rails / RSpec?


86

C'è il seguente codice:

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

Voglio provarlo tramite RSpec. Il mio codice è:

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

CarBrand con ID uguale a 0 non esiste, quindi il codice del mio controller solleva Errori :: CarBrandNotFound, ma il mio codice di prova mi dice che non è stato sollevato nulla. Come posso risolverlo? Cosa sbaglio?

Risposte:


116

Per specificare la gestione degli errori, le tue aspettative devono essere impostate su un blocco; la valutazione di un oggetto non può generare un errore.

Quindi vuoi fare qualcosa del genere:

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

Vedi Errore previsto per i dettagli.

Tuttavia, sono un po 'sorpreso che tu non abbia alcuna eccezione che ribolle ai risultati delle tue specifiche.


1
@ jakob-s il comportamento di errore previsto che stai usando qui non funziona sulle richieste del controller. Lo get :index, car_brand_id: 0stesso non solleva un errore.
Ricardo Otero

@RicardoOtero Le cose potrebbero essere cambiate, ma per quello che vale, per me lo fa: gist.github.com/koppen/0e1d0894a908a3768847 . Ma certamente, qualcosa nello stack potrebbe gestire l'errore prima che arrivi allo spec runner.
Jakob S

Questa è la risposta giusta per le attuali versioni di rspec e dovrebbe essere votata a favore
Neil Woods

È corretto. La forma corretta per testare le eccezioni sta usando {} invece di () sul metodo ad eccezione.
Luiz Henrique,

111

Usa expect{}invece di expect().


7
Vale la pena sottolineare che questo risolve il problema perché la sintassi {} crea un blocco per monitorare la data eccezione da sollevare. MiniTest ha requisiti di sintassi simili quando verifica che un blocco di codice sollevi un'eccezione.
Argus9

1
Un cambiamento così piccolo. Mi ha fatto molare le ruote per un po '. Grazie per questo.
josh

4
Non posso crederci. 1 ora di tentativi e si sta trasformando ( )in { }! Grazie mille
Simon Franzen

1
Sì, lo stesso per me - credo di aver speso di più :) per questo ho pubblicato la soluzione qui
kaleb4eg

2
So che dovrei usare i commenti per chiedere ... ma comunque, vorrei ringraziarti per la risposta. Dopo molteplici approcci finalmente ho trovato la soluzione al mio problema.
Florin Lei

18

get :index non solleverà mai un'eccezione - piuttosto imposterà la risposta in modo che sia un errore 500 in qualche modo come farebbe un server reale.

Prova invece:

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

1
Sono contento che qualcuno ne abbia parlato! :) Jakob ha cercato di educarli sul fatto che non solleverà mai un'eccezione nella risposta più votata, ma ha dovuto affrontare alcune resistenze errate. 👍
Tarek N. Elsamni
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.