nothing-special-here
nothing-special-here

Reputation: 12568

How to define Rspec custom matcher for its(:field)

I want to declare custom matcher for Rspec 2

I am using rspec 2.13 and rails 3.2.13.

I have tried to write something like this:

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

but when I use this in spec, it doesn't works Failures:

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

Spec code:

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

Edit:

I want to have reverse of logic like this:

its(:from) { should_not be_nil }

Upvotes: 1

Views: 794

Answers (2)

nothing-special-here
nothing-special-here

Reputation: 12568

Solution:

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

Looks like this helper already exists in Rspec.

I just reinvented wheel. But I will still let this answer and don't delete this post.

It will be tip for developers, how to declare custom matcher without parameter eg.

be_something_special

Upvotes: 2

gregates
gregates

Reputation: 6714

I'm not sure why you need a custom matcher at all here. Wouldn't

its(:from) { should be }

work for you?

See here: 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

Update:

Since apparently the question is how to write a custom matcher for an existing predicate present?, then the answer is: rspec already provides that, and there is still no need to write a custom matcher.

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

For any predicate #foo? on an object, you can just write should be_foo. Rspec will even define matchers for predicates that start with "has" like has_foo? with a more natural syntax, so that you can just write should have_foo.

Upvotes: 2

Related Questions