2

我正在尝试习惯于使用简单的驱动程序片段来测试我的代码,并想测试是否在不退出程序的情况下引发了参数错误。这是我正在使用的代码

class Die
  def initialize(sides)
    @sides=sides
    unless @sides>0
      raise ArgumentError.new("Your number sucks, yo")
    end
  end

  #returns the number of sides of a die
  def sides
    @sides
  end

  #generates a random die roll based on the number of sides
  def roll
    rand(@sides)+1
  end
end

这就是我试图打电话进行测试的内容。

p bad=Die.new(0)=="Your number sucks, yo"

我希望它返回的是“真实”。它在终端返回的是:

w3p1_refact.rb:33:in `initialize': Your number sucks, yo (ArgumentError)
    from w3p1_refact.rb:69:in `new'
    from w3p1_refact.rb:69:in `<main>'

我可以重写它以返回我正在寻找的东西吗?

4

1 回答 1

5

来自异常的文档

当引发异常但尚未处理(在rescue、和块中)时ensure全局变量 $! 将包含当前异常并且 $@ 包含当前异常的回溯。at_exitEND

因此,一旦我刚刚在$!全局变量中引发了异常,我就可以使用Exception#message方法,该方法返回异常的消息或名称。

你用Kernel#raise

没有参数,在 $! 中引发异常 或引发 RuntimeError 如果 $! 是零。使用单个 String 参数,引发带有字符串作为消息的 RuntimeError。否则,第一个参数应该是异常类的名称(或在发送异常消息时返回异常对象的对象)。可选的第二个参数设置与异常关联的消息,第三个参数是一个回调信息数组。异常被 begin...end 块的救援子句捕获。

我会做如下:

class Die
  def initialize(sides)
    @sides=sides
    unless @sides>0
      raise ArgumentError.new("Your number sucks, yo")
      # As per the doc you could write the above line as below also
      # raise ArgumentError, "Your number sucks, yo"
    end
  end

  #returns the number of sides of a die
  def sides
    @sides
  end

  #generates a random die roll based on the number of sides
  def roll
    rand(@sides)+1
  end
end

Die.new(0) rescue $!.message == "Your number sucks, yo"
# => true

上面的内联救援代码也可以写成:

begin
  Die.new(0)
rescue ArgumentError => e
  bad = e.message
end 
bad == "Your number sucks, yo" # => true
于 2014-01-25T17:53:15.843 回答