RSpec 如何消除 yield 并使其不命中 ensure

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

我有一个 action_action 叫 set_current_user

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 

我收到两个错误

提前致谢

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

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

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

至于单元测试,你想要的是只测试CurrentUserclass中的.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

希望对您有所帮助!

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

这是我想到的。将期望放在 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

我不确定你打算用这个来完成什么,因为你似乎只想确保 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 为零。

输出:

.set
  sets user for the block only

Finished in 0.03504 seconds (files took 0.14009 seconds to load)
1 example, 0 failures