Pergunta

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

Foi útil?

Solução

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
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top