Rspec raise_error不适用于自定义错误

时间:2017-07-11 17:52:30

标签: ruby-on-rails rspec

我有自定义错误类ApiError

class ApiError < StandardError
  attr_reader :message, :code, :details, :raw_json
  def initialize(json)
    @message  = json["message"]
    @code     = json["code"]
    @raw_json = json

    super json.to_s
  end
end

所以我试着编写几个规格进行测试,没有人通过。 第一个:

it 'raises an error' do
  expect { raise ApiError, "Some error"}.to raise_error ApiError.new("Some error")
end

它错误地与:

Failure/Error: expect { raise ApiError, "Some error"}.to raise_error ApiError, "Some error"

       expected ApiError with "Some error", got #<ApiError: Some error> with backtrace:
         # ./spec/models/...:39:in `block (4 levels) in <top (required)>'
         # ./spec/models/...:39:in `block (3 levels) in <top (required)>'

另一个令我惊讶的选择:

it 'raises an error 2' do
  expect { raise ApiError, "Some error"}.to raise_error ApiError, "Some error"
end

失败了:

Failure/Error: expect { raise ApiError, "Some error"}.to raise_error ApiError.new("Some error")

       expected #<ApiError: Some error>, got #<ApiError: Some error> with backtrace:
         # ./spec/models/...:43:in `block (4 levels) in <top (required)>'
         # ./spec/models...:43:in `block (3 levels) in <top (required)>'

那么,什么?在信息中,它们似乎相当平等。任何人都可以知道这是什么问题?而且,在spec文件中写ApiError, "123"ApiError.new("123")有什么不同?

========== UPD ==========

在ApiError类中设置message属性注释掉一个字符串,以防它没有覆盖默认值没有帮助

class ApiError < StandardError
  attr_reader :message, :code, :details, :raw_json
  def initialize(json)
    # @message  = json["message"]
    @code     = json["code"]
    @raw_json = json

    super json.to_s
  end
end

2 个答案:

答案 0 :(得分:2)

messageStandardError的属性。您正在覆盖它,并且message在您的异常对象中为nil。重命名您的属性,它应该通过

class ApiError < StandardError
  attr_reader :api_error_message, :code, :details, :raw_json
  def initialize(json)
    @api_error_message  = json["message"]
    @code     = json["code"]
    @raw_json = json

    super json.to_s
  end
end

it 'raises an error' do
  expect { raise ApiError, "Some error"}.to raise_error ApiError, "Some error"
end

<强>更新

如果您需要将message设置为json["message"]

  class ApiError < StandardError
    attr_reader :code, :details, :raw_json
    def initialize(json)
      @code     = json["code"]
      @raw_json = json

      super json["message"]
    end
  end

  it 'raises an error' do
    expect { raise ApiError, {"message" => "Some error"}}.to raise_error(ApiError, "Some error")
  end

答案 1 :(得分:0)

由于您将字符串传递给ApiError.new,因此您的自定义initialize方法最终会将例外的message设置为nil

ApiError.new("Some error").message
#=> nil

尝试使用适当的哈希进行测试:

let(:error_hash) do
  { "message" => "oops", "code" => 42 }
end

expect { raise ApiError, error_hash }.to raise_error ApiError, "oops"