我想创建一个像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)>'
因此,当我传递一个与请求 - 响应对象不同的对象时,我会发出一个错误,指出响应对象是预期的。
如果没有它,它会工作,但如果它显示一条信息性的消息,说明错误到底会更好。
在此先感谢您的帮助。
你试图在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