Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

rspec - matcher for one of choices

Tags:

ruby

rspec

I have method returning random value from the predefined array (namely: [ 'value1', 'value2']). How should I test that with rspec?

I'd like to do something like:

expect(FooClass.new.value).to be_in ['value1', 'value2']

Any way to do that? Thanks.

like image 926
Peter Butkovic Avatar asked Oct 28 '14 07:10

Peter Butkovic


3 Answers

Use this

expect(['value1', 'value2']).to include(FooClass.new.value)

Or a simple Boolean match

expect(['value1', 'value2'].include? FooClass.new.value).to be true
like image 95
Santhosh Avatar answered Sep 24 '22 06:09

Santhosh


Also, there is an or

expect('value').to eq('value1').or eq('value2')

Advantages:

  1. It sounds like normal English.
  2. The error message is a bit longer but contains all relevant info:
expected: "value1"
    got: "value"

...or:

expected: "value2"
    got: "value"
  1. As muirbot pointed out you should pass the value you are testing to expect(), not the other way.

  2. It's more flexible, it will work if someone came here looking for a solution to something like:

expect({one: 1, two: 2, three: 3}).to have_key(:one).or have_key(:first)
like image 31
Alexander Avatar answered Sep 26 '22 06:09

Alexander


If you need this behavior often, you can write your own matcher. Here is the one I wrote - you can stick this in your spec file directly or into any file included by your test suite:

RSpec::Matchers.define(:be_one_of) do |expected|
  match do |actual|
    expected.include?(actual)
  end

  failure_message do |actual|
    "expected one of #{expected}, got #{actual}"
  end
end

This has a nicer failure message than any of the other answers so far (in my opinion). For instance:

Failures:

  1) mydata is either empty or a list
     Failure/Error: expect(mydata.class).to(be_one_of([NilClass, Array]))
       expected one of [NilClass, Array], got String

Or you can customize the error message if some other wording makes more sense to you.

like image 35
jayhendren Avatar answered Sep 26 '22 06:09

jayhendren