我可以为RSpec匹配器添加别名吗?

时间:2014-08-20 12:14:31

标签: ruby rspec

我有两个与他们的名字完全相同的匹配器:

RSpec::Matchers.define :be_the_downcased_version_of do |actual|
    match do |actual|
        @actual = actual
        @expected = expected

        @actual == @expected.downcase
    end

    failure_message do |actual|
        "Expected #{@actual.inspect} to be the downcased version of #{expected.inspect}.\nIt was not: #{@actual.inspect}"
    end

    failure_message_when_negated do |actual|
        "Expected #{@actual.inspect} to not be the downcased version of #{expected.inspect}.\nIt was: #{@actual.inspect}"
    end

    description do
        "be the downcased version of #{expected.inspect}"
    end
end

RSpec::Matchers.define :return_the_downcased_version_of do |actual|
    match do |actual|
        @actual = actual
        @expected = expected

        @actual == @expected.downcase
    end

    failure_message do |actual|
        "Expected #{@actual.inspect} to be the downcased version of #{expected.inspect}.\nIt was not: #{@actual.inspect}"
    end

    failure_message_when_negated do |actual|
        "Expected #{@actual.inspect} to not be the downcased version of #{expected.inspect}.\nIt was: #{@actual.inspect}"
    end

    description do
        "be the downcased version of #{expected.inspect}"
    end
end

我可以在使用Ruby别名化方法时对它们进行别名吗?

alias_method :foo_meth, :bar_meth

2 个答案:

答案 0 :(得分:2)

是的,您可以使用RSpec的匹配器DSL定义匹配器。我知道这样做最方便的方法是在before块中重新打开示例上下文的类,并在那里使用别名。

但首先,让我们清理你的匹配器。

  1. 传递给Matchers.define的块获取预期值,而不是 实际值,作为其论点。
  2. 你不需要那些实例变量;它们的值已经在块参数中可用。
  3. 在spec / support / be_the_downcased_version_of.rb中:

    RSpec::Matchers.define :be_the_downcased_version_of do |expected|
      match do |actual|
        actual == expected.downcase
      end
    
      failure_message_for_should do |actual|
        "Expected #{actual.inspect} to be the downcased version of #{expected.inspect}.\nIt was not: #{actual.inspect}"
      end
    
      failure_message_for_should_not do |actual|
        "Expected #{actual.inspect} to not be the downcased version of #{expected.inspect}.\nIt was: #{actual.inspect}"
      end
    
      description do
        "be the downcased version of #{expected.inspect}"
      end
    
    end
    

    在spec / spec_helper.rb中为该匹配器定义的方法设置别名:

    config.before :each do
      class << self
        alias_method :return_the_downcased_version_of, :be_the_downcased_version_of
      end
    end
    

    这是另一种方法。我实际上并不是这样做的,因为它需要更多的样板,但它比以前的方法使用更少的魔力,因此它可能提供信息。只需在没有DSL的情况下实现匹配器并正常使用该方法。在spec / support / be_the_downcased_version_of.rb中:

    alias_method :return_the_downcased_version_of, :be_the_downcased_version_of
    
    def be_the_downcased_version_of(actual)
      BeTheDowncasedVersionOf.new actual
    end
    
    class BeTheDowncasedVersionOf
      def initialize(expected)
        @expected = expected
      end
    
      def matches?(actual)
        @actual = actual
        @actual == @expected.downcase
      end
    
      def failure_message_for_should
        "Expected #{@actual.inspect} to be the downcased version of #{@expected.inspect}.\nIt was not: #{@actual.inspect}"
      end
    
      def failure_message_for_should_not
        "Expected #{@actual.inspect} to not be the downcased version of #{@expected.inspect}.\nIt was: #{@actual.inspect}"
      end
    
      def description
        "be the downcased version of #{@expected.inspect}"
      end
    
    end
    

答案 1 :(得分:1)

正如cbliard评论的那样,你可以简单地做到

RSpec::Matchers.define :be_the_downcased_version_of do |expected|
  match do |actual|
    # ...
  end
  # ...
end

RSpec::Matchers.alias_matcher :return_the_downcased_version_of, :be_the_downcased_version_of

为匹配器添加别名。在我看来,这是一个非常干净的解决方案。