我在特性规范中有以下期望(非常低级,但仍然必要):
expect(Addressable::URI.parse(current_url).query_values).to include(
'some => 'value',
'some_other' => String
)
注意,第二个查询值是一个模糊匹配,因为我只是想确保它在那里,但我不能更具体。
我想把它提取到一个自定义匹配器中。我开始说:
RSpec::Matchers.define :have_query_params do |expected_params|
match do |url|
Addressable::URI.parse(url).query_values == expected_params
end
end
但这意味着我不能在这里传递{'some_other' => String}
。为了继续使用模糊匹配,我必须在自定义匹配器中使用include
匹配器。
但是,RSpec::Matchers::BuiltIn
中的任何内容都被标记为私有API,而Include
具体记录为:
# Provides the implementation for `include`.
# Not intended to be instantiated directly.
所以我的问题是**RSpec是否支持在自定义匹配器中使用内置匹配器?”””我将如何做到这一点?
4条答案
按热度按时间nwsw7zdq1#
RSpec::Matchers
似乎是一个受支持的API(它的rdoc没有另外说明),因此您可以用Ruby编写匹配器,而不是用匹配器DSL(受支持;参见the second paragraph of the custom matcher documentation),并像这样使用RSpec::Matchers#include
:spec/support/matchers.rb
spec/support/matcher_spec.rb
t30tvxxf2#
是的,您可以从自定义匹配器中调用内置的rspec匹配器。换句话说,在编写匹配器时,您可以使用普通的Rspec DSL而不是纯Ruby。查看this gist(不是我的主旨,但它帮助了我!).
我有一个非常复杂的控制器,它有一个选项卡界面,其中定义和选择的选项卡取决于模型示例的状态。我需要在:new、:create、:edit和:update操作的每个状态下测试选项卡设置。所以我写了这些匹配器:
我是这样使用它们的:
非常棒的是,能够只需要几个重复的期望块,并将它们汇总到一组自定义匹配器中,而不必用纯Ruby编写匹配器。
这为我节省了几十行代码,使我的测试更具表现力,并允许我在填充这些选项卡的逻辑发生变化时在一个地方进行更改。
还要注意,您可以在自定义匹配器中访问
assigns
和controller
等方法/变量,因此不需要显式地传递它们。最后,我本可以在规范中内联定义这些匹配器,但我选择将它们放在spec/support/matchers/controllers/posts_controller_matchers.rb中
kt06eoxx3#
您可以使用匹配器DSL而不是编写自己的
Matcher
类。这是一个有点简单。oug3syen4#
最后,我在match块中捕获了
RSpec::Expectations::ExpectationNotMetError
,这样我就可以设置一个更好的错误消息。所以我做了这样的事情:一些测试
那么在我的测试中我至少得到了一些有用的东西