¿Cuál es la sintaxis esperada para verificar los mensajes de excepción en assert_raises / must_raise de MiniTest?

86

¿Cuál es la sintaxis esperada para comprobar los mensajes de excepción en MiniTest assert_raises/ must_raise?

Estoy tratando de hacer una afirmación como la siguiente, donde "Foo"está el mensaje de error esperado:

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

Respuestas:

150

Puede utilizar la assert_raisesaserción o la 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

Si necesita probar algo en el objeto de error, puede obtenerlo de la aserción o expectativa de la siguiente manera:

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
mago
fuente
Genial, lo entiendo. Sin embargo, todavía no sé cómo hacer una afirmación sobre el mensaje de error planteado.
kfitzpatrick
3
err = -> {bar.do_it} .must_raise La sintaxis de RuntimeError no funcionó para mí, siguió generando la siguiente excepción. NoMethodError: método indefinido ʻassert_raises 'para nil: NilClass
thanikkal
2
@thanikkal Asegúrate de estar usando Minitest::Specy no Minitest::Test. El Spec DSL, incluidas las expectativas, solo está disponible cuando se usa Minitest::Spec.
blowmage
28

Para hacer valer la excepción:

assert_raises FooError do
  bar.do_it
end

Para afirmar un mensaje de excepción:

Según el documento de API , assert_raisesdevuelve la excepción coincidente para que pueda verificar el mensaje, los atributos, etc.

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

Minitest no le proporciona (todavía) una forma de verificar el mensaje de excepción real. Pero puede agregar un método auxiliar que lo haga y extender la ActiveSupport::TestCaseclase para usar en todas partes en su suite de prueba de rieles, por ejemplo: entest_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

y utilícelo en sus pruebas como:

assert_raises_with_message RuntimeError, 'Foo' do
  code_that_raises_RuntimeError_with_Foo_message
end
Desarrollador
fuente
2
Es cierto que Minitest no admite la verificación del mensaje de error, sin embargo, se puede lograr usando must_raiseporque le brinda la instancia del error para que pueda verificar el mensaje usted mismo.
bithavoc
1
Esta solución se siente mejor para mí, pero no la he usado must_raiseantes.
pumazi
Creo que esta solución no fallará si no se plantea ninguna excepción. Simplemente marque la excepción planteada para que sea la correcta. Pero si no se genera ninguna excepción, no se hace ninguna afirmación => no hay errores.
Foton
Buen punto @Foton Cambié la respuesta para reflejar esa expectativa.
Desarrollador
0

Para agregar algunos desarrollos más recientes, ha habido algunas discusiones sobre cómo agregarassert_raises_with_message cómo minitest en el pasado sin mucha suerte.

Actualmente, hay una solicitud de extracción prometedora esperando ser fusionada. Si se fusiona y cuando lo haga, podremos usarassert_raises_with_message sin tener que definirlo nosotros mismos.

Mientras tanto, existe esta pequeña y práctica joya llamada minitest-bonus-assertions que define exactamente ese método, junto con algunos otros, para que pueda usarlo de inmediato. Consulte los documentos para obtener más información.

Kostas Rousis
fuente