Qual é a sintaxe esperada para verificar mensagens de exceção em assert_raises / must_raise do MiniTest?

86

Qual é a sintaxe esperada para verificar mensagens de exceção no assert_raises/ do MiniTest must_raise?

Estou tentando fazer uma afirmação parecida com a seguinte, onde "Foo"está a mensagem de erro esperada:

proc { bar.do_it }.must_raise RuntimeError.new("Foo")
kfitzpatrick
fonte
Relacionado: stackoverflow.com/q/3454925/1569
Factor Mystic

Respostas:

150

Você pode usar a assert_raisesafirmação ou a must_raiseexpectativa.

it "must raise" do
  assert_raises RuntimeError do 
    bar.do_it
  end
  ->     { bar.do_it }.must_raise RuntimeError
  lambda { bar.do_it }.must_raise RuntimeError
  proc   { bar.do_it }.must_raise RuntimeError
end

Se você precisar testar algo no objeto de erro, poderá obtê-lo a partir da asserção ou expectativa da seguinte forma:

describe "testing the error object" do
  it "as an assertion" do
    err = assert_raises RuntimeError { bar.do_it }
    assert_match /Foo/, err.message
  end

  it "as an exception" do
    err = ->{ bar.do_it }.must_raise RuntimeError
    err.message.must_match /Foo/
  end
end
maçarico
fonte
Legal, eu entendo. No entanto, ainda estou perdido em como fazer uma afirmação sobre a mensagem de erro levantada.
kfitzpatrick
3
err = -> {bar.do_it} .must_raise RuntimeError sintaxe não funcionou para mim, ele continuou levantando a seguinte exceção. NoMethodError: método indefinido `assert_raises 'para nil: NilClass
thanikkal
2
@thanikkal Certifique-se de estar usando Minitest::Spece não Minitest::Test. O Spec DSL, incluindo as expectativas, estão disponíveis apenas durante o uso Minitest::Spec.
blowmage de
28

Para afirmar a exceção:

assert_raises FooError do
  bar.do_it
end

Para declarar mensagem de exceção:

De acordo com o documento da API , assert_raisesretorna a exceção correspondida para que você possa verificar a mensagem, os atributos etc.

exception = assert_raises FooError do
  bar.do_it
end
assert_equal('Foo', exception.message)
Jing Li
fonte
7

O Minitest não fornece (ainda) uma maneira de verificar a mensagem de exceção real. Mas você pode adicionar um método auxiliar que faça isso e estenda a ActiveSupport::TestCaseclasse para usar em qualquer lugar em sua suíte de teste do Rails, por exemplo: emtest_helper.rb

class ActiveSupport::TestCase
  def assert_raises_with_message(exception, msg, &block)
    block.call
  rescue exception => e
    assert_match msg, e.message
  else
    raise "Expected to raise #{exception} w/ message #{msg}, none raised"
  end
end

e use-o em seus testes como:

assert_raises_with_message RuntimeError, 'Foo' do
  code_that_raises_RuntimeError_with_Foo_message
end
Desenvolvedor
fonte
2
É verdade que o Minitest não suporta a verificação da mensagem de erro, no entanto, pode ser feito usando must_raiseporque fornece a instância do erro para que você mesmo possa verificar a mensagem.
bithavoc de
1
Esta solução parece melhor para mim, mas nunca usei must_raiseantes.
pumazi,
Acho que esta solução não falhará se nenhuma exceção for levantada. Você apenas verifica a exceção gerada para ser a correta. Mas se nenhuma exceção for levantada, nenhuma asserção é feita => sem erros.
Foton
bom ponto @Foton Mudei a resposta para refletir essa expectativa.
Desenvolvedor
0

Para adicionar alguns desenvolvimentos mais recentes, houve algumas discussões sobre adicionar assert_raises_with_messageao miniteste no passado, sem muita sorte.

Atualmente, há uma solicitação pull promissora aguardando para ser mesclada. Se e quando for mesclado, poderemos usar assert_raises_with_messagesem ter que defini-lo.

Nesse ínterim, existe esta pequena jóia útil chamada minitest-bonus-assertions que define exatamente esse método, junto com alguns outros, para que você possa usá-lo imediatamente. Veja a documentação para mais informações.

Kostas Rousis
fonte