Como usar o should_raise do RSpec com qualquer tipo de exceção?

211

Eu gostaria de fazer algo assim:

some_method.should_raise <any kind of exception, I don't care>

Como devo fazer isso?

some_method.should_raise exception

... não funciona.

marcgg
fonte

Respostas:

380
expect { some_method }.to raise_error

Sintaxe do RSpec 1:

lambda { some_method }.should raise_error

Consulte a documentação (para sintaxe do RSpec 1) e a documentação do RSpec 2 para obter mais informações.

Avdi
fonte
5
ahh .. Acabei de notar as chaves!
Louis Sayers
88

RSpec 2

expect { some_method }.to raise_error
expect { some_method }.to raise_error(SomeError)
expect { some_method }.to raise_error("oops")
expect { some_method }.to raise_error(/oops/)
expect { some_method }.to raise_error(SomeError, "oops")
expect { some_method }.to raise_error(SomeError, /oops/)
expect { some_method }.to raise_error(...){|e| expect(e.data).to eq "oops" }

# Rspec also offers to_not:
expect { some_method }.to_not raise_error
...

Nota: raise_errore raise_exceptionsão intercambiáveis.

RSpec 1

lambda { some_method }.should raise_error
lambda { some_method }.should raise_error(SomeError)
lambda { some_method }.should raise_error(SomeError, "oops")
lambda { some_method }.should raise_error(SomeError, /oops/)
lambda { some_method }.should raise_error(...){|e| e.data.should == "oops" }

# Rspec also offers should_not:
lambda { some_method }.should_not raise_error
...

Nota: raise_erroré um alias para raise_exception.

Documentação: https://www.relishapp.com/rspec

RSpec 2:

RSpec 1:

joelparkerhenderson
fonte
Essa foi uma ótima resposta.
Ziggy
RAISE_ERROR (/ oops /) é uma ótima maneira de verificar substring na mensagem de exceção
Serge Seletskyy
1
Obrigado por apontar que RAISE_ERROR e para raise_exception são intercambiáveis (y)
Yo Ludke
85

Em vez de lambda, use expect para:

   expect { some_method }.to raise_error

Isso se aplica a versões mais recentes do rspec, ou seja, rspec 2.0 e superior.

Veja o documento para mais informações.

racc
fonte
Eu não usaria isso para o Rspec 1, mas para o Rspec 2 ele funciona exatamente como deveria.
28612 ericraio
6
Na verdade, de acordo com o link documentação acima, esta deve ser esperar {some_method} .para RAISE_ERROR
Guilherme Garnier
Nem o seu comentário nem a página para a qual você vincula explica por que expecté melhor ou pior que lambda.
precisa saber é o seguinte
1
A expectativa é de rspec 2.0 e superior. Isso torna discutível o argumento sobre qual é o melhor, uma vez que a sintaxe lambda não funciona mais
Rob
Isso não funciona para mim em capivara:expect { visit welcome_path }.to raise_error
nnyby
65

A sintaxe mudou recentemente e agora é:

expect { ... }.to raise_error(ErrorClass)
ayckoster
fonte
4

A partir da versão 3.3 no rspec-expectionsgem, gera um aviso para um raise_error em branco sem um parâmetro

expect { raise StandardError }.to raise_error # results in warning
expect { raise StandardError }.to raise_error(StandardError) # fine

Isso dá uma dica de que seu código pode falhar com um erro diferente do que o teste pretendia verificar.

AVISO: Usar o raise_errorcombinador sem fornecer um erro ou mensagem específica corre o risco de falsos positivos, pois raise_errorcorresponderá quando Ruby gerar a NoMethodError, NameErrorou ArgumentError, potencialmente permitindo que a expectativa passe sem executar o método que você pretende chamar. Em vez disso, considere fornecer uma classe ou mensagem de erro específica. Esta mensagem pode ser suprimida por definição: RSpec::Expectations.configuration.warn_about_potential_false_positives = false.

Bruno E.
fonte