Dogweather
Dogweather

Reputation: 16809

RSpec: How to test for a boolean return type?

I'm using RSpec to test an API. I want to specify that one particular endpoint returns a boolean value, either true or false. This is an API to be used by other systems and languages, and so it's important for it to be an actual boolean, not merely something that Ruby will evaluate to false or true.

But I don't see a way to do this because there's no Boolean type in Ruby.

Upvotes: 32

Views: 26459

Answers (7)

heartpunk
heartpunk

Reputation: 2275

It's a long time later, but here's what I settled on:

foo.should satisfy {|x| [true, false].map(&:object_id).include? x.object_id}

This works because true and false only have one instance. Also, more of a curiosity, but they also always have the same instance id.

Upvotes: 2

Rimian
Rimian

Reputation: 38428

I had the same problem. This is what I came up with:

RSpec::Matchers.define :be_boolean do
  match do |actual|
    expect(actual).to be_in([true, false])
  end
end

See: https://www.relishapp.com/rspec/rspec-expectations/v/3-4/docs/custom-matchers

It can be used like so:

it 'is boolean' do
  expect(true).to be_boolean
end

Upvotes: 26

fphilipe
fphilipe

Reputation: 10054

In more recent rspec versions one can use compound matchers:

expect(thing).to be(true).or be(false)

Upvotes: 22

Rui Nunes
Rui Nunes

Reputation: 858

How about a combination of the above?

RSpec::Matchers.define :be_boolean do
  match do |value|
    [true, false].include? value
  end
end

usage:

expect(something).to be_boolean

Upvotes: 9

Tomasz Kapłon
Tomasz Kapłon

Reputation: 562

expect(variable).to be_in([true, false])

Upvotes: 41

Lorenzo Sinisi
Lorenzo Sinisi

Reputation: 470

Add the gem rspec_boolean to your Gemfile in the group :development, :test:

gem 'rspec_boolean'

And than use it like:

expect(val.is_done).to be_boolean

Upvotes: 1

BaronVonBraun
BaronVonBraun

Reputation: 4293

While Ruby doesn't have a Boolean class, it does have TrueClass and FalseClass, of which true and false are the only instances. I'm sure you could test against either of those two and be good to go.

true.is_a? TrueClass # => true
(1 == 1).is_a? TrueClass # => true
1.is_a? TrueClass # => false

false.is_a? FalseClass # => true
(1 == 2).is_a? FalseClass # => true
nil.is_a? FalseClass # => false

Upvotes: 2

Related Questions