Search code examples
rubyunit-testingrspecrspec-rails

RSpec how to stub out yield and have it not hit ensure


I have an around action_action called set_current_user

def set_current_user
  CurrentUser.set(current_user) do
    yield
  end
end

In the CurrentUser singleton

  def set(user)
    self.user = user
    yield
  ensure
    self.user = nil
  end

I cannot figure out how to stub out the yield and the not have the ensure part of the method called

Ideally I would like to do something like

it 'sets the user' do
  subject.set(user)
  expect(subject.user).to eql user
end 

Two errors I am getting

    1. No block is given
    1. When I do pass a block self.user = nil gets called

Thanks in advance


Solution

  • I am not sure what you intend to accomplish with this as it appears you just want to make sure that user is set in the block and unset afterwards. If this is the case then the following should work fine

    class CurrentUser
      attr_accessor :user
      def set(user)
        self.user = user
        yield
      ensure
        self.user = nil
      end
    end
    
    describe '.set' do
      subject { CurrentUser.new }
      let(:user) { OpenStruct.new(id: 1) }
      it 'sets user for the block only' do 
        subject.set(user) do 
          expect(subject.user).to eq(user)
        end 
        expect(subject.user).to be_nil 
      end
    end
    

    This will check that inside the block (where yield is called) that subject.user is equal to user and that afterwards subject.user is nil.

    Output:

    .set
      sets user for the block only
    
    Finished in 0.03504 seconds (files took 0.14009 seconds to load)
    1 example, 0 failures