Ruby o Rails Rspec - 如何在创建自定义匹配器时验证参数

问题描述 投票:0回答:1

我想创建一个像matcher has_http_status一样的验证到content_type。

我创建了以下匹配器:

require 'rspec/expectations'

RSpec::Matchers.define :have_content_type do |expected|
  match do |actual|
    actual.content_type == expected
  end

  description do
    "respond with content_type #{expected}"
  end
end

但是,我想检查实际值是否为响应对象。如果没有,我想给出一个像have_http_status这样的消息,它将是:

 Failure/Error: it { expect(legal_person).to have_http_status(200) }
       expected a response object, but an instance of LegalPerson was received
     # ./spec/controllers/legal_people_controller_spec.rb:105:in `block (5 levels) in <top (required)>'

因此,当我传递一个与请求 - 响应对象不同的对象时,我会发出一个错误,指出响应对象是预期的。

如果没有它,它会工作,但如果它显示一条信息性的消息,说明错误到底会更好。

在此先感谢您的帮助。

ruby-on-rails rspec
1个回答
0
投票

你试图在1个名字下有2个匹配器。我认为这是一个不好的做法,应该有两个匹配器 - 一个用于内容类型,另一个用于检查请求/响应类型。所以你的测试应该是这样的:

expect(response).to be_a(ActionDispatch::Response)
expect(response).to have_content_type('application/json')

此外,我没有看到任何内容类型检查的问题。如果传递的对象没有.content_type方法,匹配器将抛出相应的错误:Undefined method 'content_type',你应该很好地搞清楚你传递了错误的对象。

但是,如果您仍然确定需要在一个匹配器中检查两件事,请检查:

RSpec::Matchers.define :have_content_type do |expected|
  match do |actual|
    request_or_response?(actual) && actual.content_type.to_s == expected
  end

  description do |actual|
    if request_or_response?(actual)
      "respond with content_type #{expected}"
    else
      "a response object, but an instance of #{actual.class} was received"
    end
  end

  private

  def request_or_response?(actual)
    [Rack::Request, ActionDispatch::Response].any? do |klass|
      actual.is_a?(klass)
    end
  end
end
© www.soinside.com 2019 - 2024. All rights reserved.