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
我收到两个错误
- 没有给出块
- 当我通过一个方块时
self.user = nil
被调用
提前致谢
需要指出的一些可能有帮助的事情:
ensure
保留用于您想要 运行 的代码块,无论发生什么,因此您的 self.user
将始终是 nil
的原因。我想你想要的是在出现异常时将用户分配给 nil 。在这种情况下,您应该改用 rescue
。
def set(user)
self.user = user
yield
rescue => e
self.user = nil
end
至于单元测试,你想要的是只测试CurrentUser
class中的.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
我有一个 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
我收到两个错误
- 没有给出块
- 当我通过一个方块时
self.user = nil
被调用
- 当我通过一个方块时
提前致谢
需要指出的一些可能有帮助的事情:
ensure
保留用于您想要 运行 的代码块,无论发生什么,因此您的 self.user
将始终是 nil
的原因。我想你想要的是在出现异常时将用户分配给 nil 。在这种情况下,您应该改用 rescue
。
def set(user)
self.user = user
yield
rescue => e
self.user = nil
end
至于单元测试,你想要的是只测试CurrentUser
class中的.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