如何为其(:field)定义Rspec自定义匹配器

时间:2013-05-30 16:22:22

标签: ruby-on-rails ruby-on-rails-3 macros rspec

我想为Rspec 2声明自定义匹配器

我正在使用rspec 2.13rails 3.2.13

我试着写这样的东西:

RSpec::Matchers.define :be_present do |expected|
  match do
    expected !be_empty
  end
end

但是当我在规范中使用它时,它不起作用 故障:

  1) NewsletterMailer.send_newsletter_to_groups from 
     Failure/Error: its(:from) { should be_present }
     ArgumentError:
       wrong number of arguments (1 for 0)

规格代码:

describe NewsletterMailer do

  describe '.send_newsletter_to_emails' do
    let(:user) { create(:admin) }
    let(:user2) { create(:user) }
    subject { NewsletterMailer.send_newsletter_to_emails(newsletter.id, "#{user.email}, #{user2.email}") }

    its(:to) { should == [user.email, user2.email] }
    its(:from) { should be_present }
    its(:subject) { should be }
  end

修改

我想反过来这样的逻辑:

its(:from) { should_not be_nil }

2 个答案:

答案 0 :(得分:2)

解决方案:

RSpec::Matchers.define :be_present do |expected|
  match do |actual|
    actual && actual.present?
  end
end

看起来这个助手已经存在于Rspec。

我刚刚重新发明轮子。但我仍然会回答这个问题而不删除这篇文章。

这将是开发人员的提示,如何声明没有参数的自定义匹配器,例如。

be_something_special

答案 1 :(得分:2)

我不确定为什么你需要一个自定义匹配器。不会

its(:from) { should be }

为你工作?

见这里: https://www.relishapp.com/rspec/rspec-expectations/v/2-3/docs/built-in-matchers/be-matchers#be-matcher

obj.should be # passes if obj is not nil

<强>更新

由于显然问题是如何为现有谓词{{​​1}}编写自定义匹配器,所以答案是:rspec已经提供了这个,并且仍然不需要编写自定义匹配器。

https://www.relishapp.com/rspec/rspec-expectations/v/2-3/docs/built-in-matchers/predicate-matchers

对于对象上的任何谓词present?,您只需编写#foo?即可。 Rspec甚至会为谓词定义匹配器,这些谓词以“has”开头,如should be_foo,语法更自然,因此您只需编写has_foo?