ruby-on-rails - 以任意顺序匹配多个 yield

标签 ruby-on-rails ruby rspec iterator yield

我想用 rspec 测试一个迭代器。在我看来,唯一可能的产量匹配器是 yield_successive_args (根据 https://www.relishapp.com/rspec/rspec-expectations/v/3-0/docs/built-in-matchers/yield-matchers )。其他匹配器仅用于单个屈服。

但是 yield_successive_args 如果屈服顺序与指定顺序不同,则会失败。

是否有任何方法或很好的解决方法来测试以任何顺序产生的迭代器?

类似下面的内容:

expect { |b| array.each(&b) }.to yield_multiple_args_in_any_order(1, 2, 3)

最佳答案

这是我为这个问题想出的匹配器,它相当简单,并且应该以很高的效率工作。

require 'set'

RSpec::Matchers.define :yield_in_any_order do |*values|
  expected_yields = Set[*values]
  actual_yields = Set[]

  match do |blk|
    blk[->(x){ actual_yields << x }]    # ***
    expected_yields == actual_yields    # ***
  end

  failure_message do |actual|
    "expected to receive #{surface_descriptions_in expected_yields} "\
    "but #{surface_descriptions_in actual_yields} were yielded."
  end

  failure_message_when_negated do |actual|
    "expected not to have all of "\
    "#{surface_descriptions_in expected_yields} yielded."
  end

  def supports_block_expectations?
    true
  end
end

我用 # *** 突出显示了包含大部分重要逻辑的行。这是一个非常简单的实现。

用法

只需将它放在一个文件中,在 spec/support/matchers/ 下,并确保您从需要它的规范中需要它。大多数时候,人们只是添加这样一行:

Dir[File.dirname(__FILE__) + "/support/**/*.rb"].each {|f| require f}

到他们的 spec_helper.rb 但是如果你有很多支持文件,而且它们并不是到处都需要,这可能会有点多,所以你可能只想把它包含在什么地方它被使用。

然后,在规范本身中,用法就像任何其他产生匹配器的用法一样:

class Iterator
  def custom_iterator
    (1..10).to_a.shuffle.each { |x| yield x }
  end
end

describe "Matcher" do
  it "works" do
    iter = Iterator.new
    expect { |b| iter.custom_iterator(&b) }.to yield_in_any_order(*(1..10))
  end
end

关于ruby-on-rails - 以任意顺序匹配多个 yield ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24492512/

相关文章:

ruby-on-rails - 如何使用 rspec/rails 测试 AJAX 请求的路由

ruby-on-rails - 在 Rspec 请求规范中设置 session 变量

ruby-on-rails - rails : Why “collection=” doesn't update records with existing id?

ruby-on-rails - Rails 迁移文件失败 - Mysql2::Error: 列数据被截断

javascript - 哪些形式的 JavaScript 适合中级 Rails 开发人员(仅团队中的开发人员)?

ruby-on-rails - 有没有一种 Rails 方法可以翻译模型名称以用于标题(即 titleize?)

jquery_ujs 问题 : Font Awesome animated spinner works in Chrome but Not Safari

ruby-on-rails - 无方法错误 : undefined method `created_at' for in Rails

ruby-on-rails - 如何在 Rails 项目中使用修改后的第三方库?

ruby-on-rails - 如何减少 rspec 测试依赖性?