Quelle est la syntaxe attendue pour vérifier les messages d'exception dans assert_raises / must_raise de MiniTest?

86

Quelle est la syntaxe attendue pour vérifier les messages d'exception dans MiniTest's assert_raises/ must_raise?

J'essaye de faire une assertion quelque chose comme ce qui suit, où se "Foo"trouve le message d'erreur attendu:

proc { bar.do_it }.must_raise RuntimeError.new("Foo")
kfitzpatrick
la source
En relation: stackoverflow.com/q/3454925/1569
Factor Mystic

Réponses:

150

Vous pouvez utiliser l' assert_raisesassertion ou l' must_raiseattente.

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 vous avez besoin de tester quelque chose sur l'objet d'erreur, vous pouvez l'obtenir à partir de l'assertion ou de l'attente comme suit:

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
fellation
la source
Cool, je comprends ça. Cependant, je ne sais toujours pas comment faire une assertion sur le message de l'erreur soulevée.
kfitzpatrick
3
err = -> {bar.do_it} .must_raise La syntaxe RuntimeError n'a pas fonctionné pour moi, elle a continué à soulever l'exception suivante. NoMethodError: méthode non définie ʻassert_raises 'pour nil: NilClass
thanikkal
2
@thanikkal Assurez-vous que vous utilisez Minitest::Specet non Minitest::Test. Les spécifications DSL, y compris les attentes, ne sont disponibles que lors de l'utilisation Minitest::Spec.
blowmage
28

Pour affirmer une exception:

assert_raises FooError do
  bar.do_it
end

Pour affirmer un message d'exception:

Conformément à la documentation de l'API , assert_raisesrenvoie l'exception correspondante afin que vous puissiez vérifier le message, les attributs, etc.

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

Minitest ne vous fournit pas (encore) de moyen de vérifier le message d'exception réel. Mais vous pouvez ajouter une méthode d'assistance qui le fait et étendre la ActiveSupport::TestCaseclasse pour l'utiliser partout dans votre suite de tests de rails, par exemple: intest_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

et utilisez-le dans vos tests comme:

assert_raises_with_message RuntimeError, 'Foo' do
  code_that_raises_RuntimeError_with_Foo_message
end
Développeur
la source
2
Il est vrai que Minitest ne prend pas en charge la vérification du message d'erreur, mais cela peut être réalisé en utilisant, must_raisecar il vous donne l'instance de l'erreur afin que vous puissiez vérifier le message vous-même.
bithavoc
1
Cette solution me convient mieux, mais je ne l'ai jamais utilisée must_raiseauparavant.
pumazi
Je pense que cette solution n'échouera pas si aucune exception n'est levée. Vous vérifiez simplement l'exception levée pour être la bonne. Mais si aucune exception n'est levée, aucune assertion n'est effectuée => aucune erreur.
Foton
bon point @Foton J'ai changé la réponse pour refléter cette attente.
Développeur
0

Pour ajouter des développements plus récents, il y a eu des discussions sur l'ajout assert_raises_with_messagede minitest dans le passé sans beaucoup de chance.

Actuellement, une pull request prometteuse attend d'être fusionnée. Si et quand il est fusionné, nous pourrons l'utiliser assert_raises_with_messagesans avoir à le définir nous-mêmes.

En attendant, il y a ce petit bijou pratique nommé minitest-bonus-assertions qui définit exactement cette méthode, avec quelques autres, afin que vous puissiez l'utiliser hors de la boîte. Consultez la documentation pour plus d'informations.

Kostas Rousis
la source