我想断言一个数组至少包含一个通过RSpec期望的元素。但是数组中的大多数元素都不会超出期望。所以我想做这样的事情:
it "finds one element that matches" do
array.any? do |element|
expect(element).to eq("expected value")
end
end
如果任何元素通过期望,则通过测试。但是,当然,正如我在此处编写的那样,测试将失败。
RSpec中是否有一种模式可以完成我想完成的事情?
我不想这样做:
it "finds one element that matches" do
expect(array.any? {|val| val == "expected value"}).to be_true
end
因为我不清楚如何手动检查与测试中需要使用的匹配器相同的东西。我想使用have_attributes
匹配器,它做了一些subtle metaprogramming magic,我不想冒险尝试自己重新实现。
答案 0 :(得分:3)
您可以将include
匹配器用于compose matchers:
expect(array).to include(a_string_matching(/foo/))
尽管语法有些笨拙,但您可以将其与have_attributes
一起使用:
expect(obj).to have_attributes(tags: include(a_string_matching(/foo/))
但是如果由于某种原因不够灵活,您可以使用satisfy
匹配器:
expect(array).to satisfy {|arr| arr.any? {|val| val == "expected value"})
双重嵌套的块本身有点笨拙,但是满足的灵活性使您可以用它来做各种事情,并且可以使用include
匹配器将您带到那里。例如:
require "rspec"
require "ostruct"
obj = OpenStruct.new(name: "foobar", tags: %w(bin bazzle))
describe obj do
it "has a bin tag" do
is_expected.to have_attributes(tags: include(/bin/))
end
it "has a tag 3 characters long" do
is_expected.to have_attributes(tags: include(satisfy { |t| t.length == 3 }))
end
end
如果您愿意添加一个宝石,我很喜欢rspec-its在以下情况下:他们可以清理对象的各个属性的规范,而这些属性并不能很好地保证其自身的主题范围:< / p>
describe obj do
its(:tags) { is_expected.to be_a Array }
its(:tags) { is_expected.to include "bin" }
end
答案 1 :(得分:0)
RSpec具有composing matchers,可与expect(array).to include
配合使用以实现我想要的功能。例如:
expect(array).to include(a_string_matching("expected value"))
对于have_attributes
匹配器,RSpec为此有一个别名an_object_having_attributes
,让我这样写:
expect(array).to include(an_object_matching(object_i_want_duplicated))