链接Rspec自定义匹配器

时间:2013-05-02 09:46:40

标签: ruby rspec

出于测试原因,我最近移动了一些RSpec匹配器来使用类形式而不是DSL。有没有办法在这种形式下轻松获得链接行为。

E.g。

class BeInZone
  def initialize(expected)
    @expected = expected
  end
  def matches?(target)
    @target = target
    @target.current_zone.eql?(Zone.new(@expected))
  end
  def failure_message
    "expected #{@target.inspect} to be in Zone #{@expected}"
  end
  def negative_failure_message
    "expected #{@target.inspect} not to be in Zone #{@expected}"
  end
  # chain methods here
end

非常感谢

2 个答案:

答案 0 :(得分:3)

添加一个名为chain的新方法,通常应返回self。通常,您保存提供的链式状态。然后,您可以更新要使用的matches?方法。此状态也可用于各种输出消息方法。

所以对你的例子来说:

class BeInZone
  # Your code

  def matches?(target)
    @target = target

    matches_zone? && matches_name?
  end

  def with_name(name)
    @target_name = name
    self
  end

  private
  def matches_zone?
    @target.current_zone.eql?(Zone.new(@expected))
  end

  def matches_name?
    true unless @target_name

    @target =~ @target_name
  end
end

然后使用它:expect(zoneA_1).to be_in_zone(zoneA).with_name('1')

这样做的原因是您正在构建要传递给shouldexpect(object).to方法的对象。然后,这些方法在提供的对象上调用matches?

所以它与其他红宝石代码如puts "hi there".reverse.upcase.gsub('T', '7')没什么不同。在这里,字符串"hi there"是您的匹配器,并在其上调用链接方法,将从gsub返回的最终对象传递给puts

内置的期望change匹配器是一个很好的例子。

答案 1 :(得分:0)

我写了一篇关于这个主题的教程 请参阅: www.danielcsite.com/rspec_custom_matchers
在本教程中,我将详细介绍并使用屏幕截图如何编写自定义匹配器类并通过链接多种方法来调用它。