期望断言仅对数组中的一个元素成立

时间:2019-06-06 16:23:56

标签: ruby rspec

我想断言一个数组至少包含一个通过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,我不想冒险尝试自己重新实现。

2 个答案:

答案 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))