首页 文章

RSpec如何产生收益并且没有命中确保

提问于
浏览
0

我有一个名为 set_current_user 的action_action

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

在CurrentUser单例中

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

我无法弄清楚如何将产量存根并且没有被调用方法的确保部分

理想情况下我想做点什么

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

我得到的两个错误

  • 没有给出阻止

  • 当我传递一个块时 self.user = nil 被调用

提前致谢

3 回答

  • 1

    需要指出的一些事情可能会有所帮助:

    ensure 保留用于您想要运行的代码块,无论发生什么情况,因此 self.user 始终为 nil 的原因 . 我认为你想要的是如果有异常则将用户分配给nil . 在这种情况下,您应该使用 rescue .

    def set(user)
      self.user = user
      yield
    rescue => e
      self.user = nil
    end
    

    至于单元测试,你想要的只是测试 CurrentUser 类中的 .set 方法 . 假设您在周围的过滤器中正确连接了所有内容,这里有一个可能适合您的示例:

    describe CurrentUser do
      describe '.set' do
        let(:current_user) { create(:user) } 
        subject do
          CurrentUser.set(current_user) {}
        end
        it 'sets the user' do
          subject
          expect(CurrentUser.user).to eq(current_user)
        end 
      end
    end
    

    希望这可以帮助!

  • 0

    我不确定你打算用这个做什么,因为看起来你只是想确保在块中设置 user 然后取消设置 . 如果是这种情况,那么以下应该可以正常工作

    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
    

    这将检查块内(调用yield的位置) subject.user 等于 user ,之后 subject.user 为零 .

    Output

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

    我没有提到我需要在每次请求后清除用户 .

    这就是我提出的 . 把它的期望放在lambda中有点疯狂,但确保用户在处理请求之前设置并在之后清除它

    describe '.set' do
      subject { described_class }
    
      let(:user) { OpenStruct.new(id: 1) }
    
      let(:user_expectation) { lambda{ expect(subject.user).to eql user } }
    
      it 'sets the user prior to the block being processed' do
        subject.set(user) { user_expectation.call }
      end
    
      context 'after the block has been processed' do
        # This makes sure the user is always cleared after a request
        # even if there is an error and sidekiq will never have access to it.
    
        before do
          subject.set(user) { lambda{} }
        end
    
        it 'clears out the user' do
          expect(subject.user).to eql nil
        end
      end
    end
    

相关问题