Rspec raise_error 不适用于自定义错误

Ngo*_*ral 5 rspec ruby-on-rails

我有一个自定义错误类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
Run Code Online (Sandbox Code Playgroud)

所以我尝试写了几个规范来测试它,但没有人通过。第一:

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

它失败了:

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)>'
Run Code Online (Sandbox Code Playgroud)

还有一个让我很惊讶的选择:

it 'raises an error 2' do
  expect { raise ApiError, "Some error"}.to raise_error ApiError, "Some error"
end
Run Code Online (Sandbox Code Playgroud)

它失败了:

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)>'
Run Code Online (Sandbox Code Playgroud)

所以呢?在消息中,他们看起来相当平等。谁能知道有什么问题吗?而且,书写ApiError, "123"ApiError.new("123")规范文件有什么区别?

==========更新==========

通过在 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
Run Code Online (Sandbox Code Playgroud)

ush*_*sha 5

message是 的一个属性StandardError。您正在覆盖它并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
Run Code Online (Sandbox Code Playgroud)

更新:

如果您需要设置messagejson["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
Run Code Online (Sandbox Code Playgroud)