Search code examples
rspec2rspec-rails

how to pass block to RSpec "with" expectation


Tet say I have class

Class Foo < ActiveRecord::Base

  def set_publication
      Publication.new do |publication|
        publication.owner_type = 'Foo'
        publication.owner_id   =  123
      end
      return 'something else'
  end
end

Question: How can I test the block that Publication new instance will receive

describe Foo, 'set_publication' do
  let(:foo){ Foo.new }

  it do
    Publication.should_recive(:new).with( ??????? ).and_return( double(:something) )
    foo.set_publication
  end
end

of course this is just a example of much complicated functionality in which I cannot use hash arguments like this

Class Foo < ActiveRecord::Base

  def set_publication
     Publication.new owner_type: 'Foo', owner_id: 123         
     return 'something else'
  end
end

and test it like this

describe Foo, 'set_publication' do
  let(:foo){ Foo.new }

  it do
    Publication.should_recive(:new).with( owner_type: "Foo", owner_id: 123 ).and_return( double(:something) )
    foo.set_publication
  end
end

thank you


UPDATE: It seems it's bit unclear what I'm asking here, so :

I'm looking for way to ensure that Publication.new was called explicitly with set of arguments, in this case a block

so I suppose something like this

Publication.should_receive(:new).with(&block) # example

where the block parameters owner_type == 'foo' and owner_id == 123


Solution

  • You can use and_yield to accomplish this.

    class Foo
      def set_publication
        Publication.new do |publication|
          publication.owner_type = 'Foo'
          publication.owner_id   =  123
        end
        return 'something else'
      end
    end
    
    class Publication
      attr_accessor :owner_id, :owner_type
    
      def initialize
        yield self if block_given?
      end
    end
    

    and the spec

    describe Foo do 
      let(:foo) { Foo.new }
      let!(:publication) { Publication.new }
    
      it do
        Publication.should_receive(:new).and_yield(publication)
    
        foo.set_publication
    
        publication.owner_type.should eq 'Foo'
        publication.owner_id.should eq 123
      end
    end