Jaka jest oczekiwana składnia do sprawdzania komunikatów wyjątków w assert_raises / must_raise MiniTest?

86

Jaka jest oczekiwana składnia do sprawdzania komunikatów o wyjątkach w assert_raises/ must_raise?

Próbuję utworzyć asercję podobną do poniższej, gdzie "Foo"jest oczekiwany komunikat o błędzie:

proc { bar.do_it }.must_raise RuntimeError.new("Foo")
kfitzpatrick
źródło
Związane z: stackoverflow.com/q/3454925/1569
Factor Mystic

Odpowiedzi:

150

Możesz użyć assert_raisestwierdzenia lub must_raiseoczekiwania.

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

Jeśli chcesz coś przetestować na obiekcie błędu, możesz to uzyskać z asercji lub oczekiwania w następujący sposób:

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
blowmage
źródło
Fajnie, rozumiem. Jednak nadal nie wiem, jak dokonać asercji w komunikacie o podniesionym błędzie.
kfitzpatrick
3
err = -> {bar.do_it} .must_raise Składnia RuntimeError nie działała dla mnie, zgłaszała następujący wyjątek. NoMethodError: undefined method `assert_raises 'for nil: NilClass
thanikkal
2
@thanikkal Upewnij się, że używasz, Minitest::Speca nie Minitest::Test. Spec DSL, w tym oczekiwania, są dostępne tylko podczas używania Minitest::Spec.
blowmage
28

Aby zgłosić wyjątek:

assert_raises FooError do
  bar.do_it
end

Aby potwierdzić komunikat o wyjątku:

Zgodnie API doc , assert_raiseszwraca wyjątek dopasowane, dzięki czemu można sprawdzić wiadomość, atrybuty itp

exception = assert_raises FooError do
  bar.do_it
end
assert_equal('Foo', exception.message)
Jing Li
źródło
8

Program Minitest nie zapewnia (jeszcze) sposobu sprawdzenia rzeczywistego komunikatu o wyjątku. Ale możesz dodać metodę pomocniczą, która to robi i rozszerzyć ActiveSupport::TestCaseklasę tak, aby była używana wszędzie w zestawie testów rails, np. Wtest_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

i używaj go w swoich testach, takich jak:

assert_raises_with_message RuntimeError, 'Foo' do
  code_that_raises_RuntimeError_with_Foo_message
end
Deweloper
źródło
2
To prawda, że ​​Minitest nie obsługuje sprawdzania komunikatu o błędzie, jednak można to osiągnąć za pomocą, must_raiseponieważ podaje wystąpienie błędu, dzięki czemu możesz samodzielnie sprawdzić komunikat.
bithavoc
1
To rozwiązanie wydaje mi się lepsze, ale wcześniej nie korzystałem must_raise.
pumazi
Myślę, że to rozwiązanie nie zawiedzie, jeśli nie zostanie zgłoszony wyjątek. Po prostu sprawdzasz podniesiony wyjątek, aby był poprawny. Ale jeśli nie zostanie zgłoszony żaden wyjątek, żadne potwierdzenie nie zostanie wykonane => brak błędów.
Foton
dobra uwaga @Foton Zmieniłem odpowiedź, aby odzwierciedlić to oczekiwanie.
Deweloper
0

Aby dodać trochę nowszych osiągnięć, w przeszłości toczyły się dyskusje na temat dodawania assert_raises_with_messagedo minitest bez większego szczęścia.

Obecnie na scalenie czeka obiecujące żądanie ściągnięcia . Jeśli i kiedy zostanie scalony, będziemy mogli z niego korzystać assert_raises_with_messagebez konieczności samodzielnego definiowania.

W międzyczasie jest ten poręczny mały klejnot o nazwie minitest-bonus-assertions, który definiuje dokładnie tę metodę wraz z kilkoma innymi, dzięki czemu można jej używać po wyjęciu z pudełka. Więcej informacji można znaleźć w dokumentacji .

Kostas Rousis
źródło