2016-11-28 42 views
1

我正在使用minitest來測試引發異常的方法。我使用了在​​中描述的技術,但我有一些混亂的結果:NoMethodError:未定義的方法`RuntimeError'當我使用{...}語法代替do ... end with minitest

代碼:

class Formatter 
    def output_report 
    raise "Abstract method called: #{__method__}" 
    end 
end 

測試:

require 'minitest/autorun' 
require_relative 'formatter' 

class TestFormatter < Minitest::Test 
    def setup 
    @formatter = Formatter.new 
    end 

    def test_formatter_error_when_abstract_method_called 
    err = assert_raises RuntimeError { @formatter.output_report } 
    assert_equal "Abstract method called: output_report", err.message 
    end 
end 

我預期測試通過​​,除了相反,我得到了以下錯誤:

Run options: --seed 64742 

# Running: 

E 

Finished in 0.001274s, 784.9294 runs/s, 0.0000 assertions/s. 

    1) Error: 
TestFormatter#test_formatter_error_when_abstract_method_called: 
NoMethodError: undefined method `RuntimeError' for #<TestFormatter:0x007fd07a2b93d0> 
    test_formatter.rb:10:in `test_formatter_error_when_abstract_method_called' 

1 runs, 0 assertions, 0 failures, 1 errors, 0 skips 

但是,如果我使用do...end塊語法,而不是{...},則測試通過

做...結束:

require 'minitest/autorun' 
require_relative 'formatter' 

class TestFormatter < Minitest::Test 
    def setup 
    @formatter = Formatter.new 
    end 

    def test_formatter_error_when_abstract_method_called 
    # err = assert_raises RuntimeError { @formatter.output_report } 
    err = assert_raises RuntimeError do 
     @formatter.output_report 
    end 
    assert_equal "Abstract method called: output_report", err.message 
    end 
end 

輸出:

Run options: --seed 37315 

# Running: 

. 

Finished in 0.001298s, 770.4160 runs/s, 1540.8321 assertions/s. 

1 runs, 2 assertions, 0 failures, 0 errors, 0 skips 

這究竟是爲什麼?我認爲do...end等於{...},除了在製作多行塊時使用前者的慣例?

回答

2

do..end{...}之間有顯着性差異:優先事項很重要。捲毛是貪婪的,do...end不是。

人爲的例子:

puts [1].each { |i| i } #⇒ 1 
puts [1].each do |i| i end #⇒ #<Enumerator:0x000000067dd678> 

這就是說,要使花括號按預期方式工作,應該使用圓括號:

assert_raises(RuntimeError) { @formatter.output_report } 
+0

我想我得到它,所以你的第一個例子中的花括號是貪婪,所以塊先得到運行。但在第二個'puts'打印出[1] .each'之後纔有機會運行該塊?而'[1] .each'是碰巧是一個枚舉器的對象,這就是爲什麼我們得到一些枚舉器打印? ''[1] .each.class#=>枚舉器' – mbigras

+1

@mbigras:要更清楚,第一個是這樣的:'puts([1] .each {| i | i})',第二個就像這個:'puts([1] .each){| i |我}'。在第一種情況下,塊被傳遞給'each'並執行,然後每個都返回'[1]'(因爲每個塊都返回接收者)。在第二種情況下,'[1] .each'在沒有塊的情況下被評估(並且返回一個Enumerator對象),然後塊被傳遞給'puts'(它完全忽略它)。 – philomory

相關問題