Domanda

I have a method #get_something which returns a complex object. I want to check, if a specific public attribute of this complex object eqals a string.

This is how I know I can test this:

require 'rspec/autorun'

class MySubject
  ComplexObject = Struct.new(:type, :trustworthiness)

  def get_something
    ComplexObject.new('serious', 100)
  end
end

RSpec.describe MySubject do
  describe '#get_something' do
    it 'returns an serious object' do
      expect(subject.get_something.type).to eq('serious')
    end

    it 'returns an trustworthy object' do
      expect(subject.get_something.trustworthiness).to be > 90
    end
  end
end

I wonder if there is a way to write the expectation like this:

expect(subject.get_something).to have_attribute(:type).to eq('serious')
expect(subject.get_something).to have_attribute(:trustworthiness).to be > 90

The reason behind this is that I want to make clear I am interested in the result of #get_something and not in the ComplexObject instance.

Is there already a matcher for this scenario? If not, how would you write this spec, especially when you are interested that more than one attribute is set correctly?

Thanks in advance

È stato utile?

Soluzione

Matchers don't have a to method that you would use like that. They take a single expected argument and are evaluated for truthiness, so you'd need to pass a hash, as in:

expect(subject.get_something).to have_attribute(method: :type, value: 'serious')
expect(subject.get_something).to have_attribute(method: :trustworthiness, value: ->(v) { v > 90 } )

with obvious complexity for interpreting the value parameter

Another approach would be to use the its functionality, which moved to a separate gem in RSpec 3, as in:

RSpec.describe MySubject do
  describe '#get_something' do
    subject(:get_something) { MySubject.new.get_something }
    its(:type) { should eq 'serious'}
    its(:trustworthiness) { should be > 90 }
  end
end
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top