Oauth 模型关注测试覆盖率存根
Oauth Model Concern Test Coverage Stubs
我正在尝试找出对此 class 达到 100% 测试覆盖率的最佳方法。我已经概述了我的完整规格,我希望有人能指出我正确的方向。我的假设是存根 Oauth2 请求会做到这一点,但我似乎无法做到这一点。
我正在使用 Rails 4.
规格
RSpec.describe 'AppOmniAuthentication', type: :concern do
let(:klass) { User }
let(:user) { create(:user) }
let(:user_oauth_json_response) do
unfiltered_oauth_packet = load_json_fixture('app_omni_authentication_spec')
unfiltered_oauth_packet['provider'] = unfiltered_oauth_packet['provider'].to_sym
unfiltered_oauth_packet['uid'] = unfiltered_oauth_packet['uid'].to_i
unfiltered_oauth_packet
end
before do
OmniAuth.config.test_mode = true
OmniAuth.config.mock_auth[:app] = OmniAuth::AuthHash.new(
user_oauth_json_response,
credentials: { token: ENV['APP_CLIENT_ID'], secret: ENV['APP_CLIENT_SECRET'] }
)
end
describe '#from_omniauth' do
let(:app_oauth) { OmniAuth.config.mock_auth[:app] }
it 'returns varying oauth related data for Bigcartel OAuth response' do
data = klass.from_omniauth(app_oauth)
expect(data[:provider]).to eq(user_oauth_json_response['provider'].to_s)
expect(data[:uid]).to eq(user_oauth_json_response['uid'].to_s)
expect(data[:email]).to eq(user_oauth_json_response['info']['email'])
expect(data[:customer_ids]).to eq(user_oauth_json_response['extra']['raw_info']['customer_ids'])
end
end
describe '#refresh_access_token!' do
it 'false if OAuth2 Fails' do
allow(user).to receive(:access_token) { true }
allow(user).to receive(:refresh_access_token!) { false }
allow(user).to receive(:result).and_raise(OAuth2::Error)
expect(user.refresh_access_token!).to be_falsey
end
it 'false if refresh fails' do
allow(user).to receive(:access_token) { true }
allow(user).to receive(:refresh_access_token!) { false }
expect(user.refresh_token!).to be_falsey
end
it 'true if new token' do
allow(user).to receive(:access_token) { true }
allow(user).to receive(:refresh_access_token!) { true }
expect(user.refresh_token!).to be_truthy
end
it 'true when refreshed' do
auth_token = OpenStruct.new(token: FFaker::Lorem.characters(50),
refresh_token: FFaker::Lorem.characters(50),
expires_at: 5.days.from_now)
allow(user).to receive_message_chain('access_token.refresh!') { auth_token }
expect(user.refresh_access_token!).to be_truthy
end
end
describe '#refresh_token!' do
it 'false if no access token' do
allow(user).to receive(:access_token) { false }
expect(user.refresh_token!).to be_falsey
end
it 'false if refresh fails' do
allow(user).to receive(:access_token) { true }
allow(user).to receive(:refresh_access_token!) { false }
expect(user.refresh_token!).to be_falsey
end
it 'true if new token is saved' do
allow(user).to receive(:access_token) { true }
allow(user).to receive(:refresh_access_token!) { true }
expect(user.refresh_token!).to be_truthy
end
end
describe '#token expired?' do
it 'true if valid' do
expect(user.token_expired?).to be_falsey
end
it 'false if expired' do
user.token_expires_at = 10.days.ago
expect(user.token_expired?).to be_truthy
end
end
end
更新
我将当前规范更改为:
it 'false if OAuth2 Fails' do
allow(OAuth2::AccessToken).to receive(:access_token) { Class.new }
allow(OAuth2::AccessToken).to receive_message_chain('access_token.refresh!') { raise OAuth2::Error.new('ERROR') }
binding.pry
end
但是,现在我收到以下错误:
WebMock::NetConnectNotAllowedError: Real HTTP connections are disabled. Unregistered request..
看来关键是这里的第二行:
def refresh_access_token!
result = access_token.refresh!
store_token(result)
save
rescue OAuth2::Error
false
end
所有其他测试存根 access_token
。如果您有一个调用真实方法的测试,它将覆盖 access_token
、client
、strategy
和 settings
.
中缺失的行
现在 strategy
、settings
和 client
都很无聊:前两个基本上只是常量。 client
仅仅通过初始化它并没有做任何事情。所以打电话给那些应该没什么大不了的。只剩下 access_token
。你可以看到它初始化了一个 OAuth2::AccessToken
,它的代码是 on Github。初始化程序也很无聊。它只是保存输入供以后使用。
所以我会存根它的 refresh!
方法:一次给 return 一个看起来有效的刷新令牌,一次引发一个 OAuth2::Error
。您可以使用 expect_any_instance_of
来做到这一点。如果这让你感到不安,你也可以存根 :new
本身,并拥有它 return 你自己的假对象:
o = expect(OAuth2::AccessToken).to receive(:new) { Object.new }
expect(o).to receive(:refresh!) { raise OAuth2::Error.new("something here") }
看起来构建一个 OAuth2::Error
可能有点麻烦,因为它 takes a request object,但我没有看到那里有什么太复杂的东西,只是乱七八糟。
那应该会给你 100% 的覆盖率!
(代表问题作者发布解决方案).
现在已经解决了。
describe '#refresh_access_token!' do
it 'false if OAuth2 Fails' do
response = OpenStruct.new(error: 'ERROR')
allow(OAuth2::AccessToken).to receive_message_chain(:new, :refresh!) { raise OAuth2::Error.new(response) }
expect(user.refresh_token!).to be_falsey
end
it 'true if new token' do
allow(OAuth2::AccessToken).to receive_message_chain(:new, :refresh!) { @auth_token }
expect(user.refresh_token!).to be_truthy
end
end
存根令牌如下所示:
@auth_token = OpenStruct.new(token: FFaker::Lorem.characters(50),
refresh_token: FFaker::Lorem.characters(50),
expires_at: 5.days.from_now)
在研究了 Paul Jungwirth 发布的概念后,将 gem 中的方法存根阻止了 Webmock 警报的触发(如预期的那样),我可以正确触发加注。加注也必须与 gem 的响应设置相匹配。
我正在尝试找出对此 class 达到 100% 测试覆盖率的最佳方法。我已经概述了我的完整规格,我希望有人能指出我正确的方向。我的假设是存根 Oauth2 请求会做到这一点,但我似乎无法做到这一点。
我正在使用 Rails 4.
规格
RSpec.describe 'AppOmniAuthentication', type: :concern do
let(:klass) { User }
let(:user) { create(:user) }
let(:user_oauth_json_response) do
unfiltered_oauth_packet = load_json_fixture('app_omni_authentication_spec')
unfiltered_oauth_packet['provider'] = unfiltered_oauth_packet['provider'].to_sym
unfiltered_oauth_packet['uid'] = unfiltered_oauth_packet['uid'].to_i
unfiltered_oauth_packet
end
before do
OmniAuth.config.test_mode = true
OmniAuth.config.mock_auth[:app] = OmniAuth::AuthHash.new(
user_oauth_json_response,
credentials: { token: ENV['APP_CLIENT_ID'], secret: ENV['APP_CLIENT_SECRET'] }
)
end
describe '#from_omniauth' do
let(:app_oauth) { OmniAuth.config.mock_auth[:app] }
it 'returns varying oauth related data for Bigcartel OAuth response' do
data = klass.from_omniauth(app_oauth)
expect(data[:provider]).to eq(user_oauth_json_response['provider'].to_s)
expect(data[:uid]).to eq(user_oauth_json_response['uid'].to_s)
expect(data[:email]).to eq(user_oauth_json_response['info']['email'])
expect(data[:customer_ids]).to eq(user_oauth_json_response['extra']['raw_info']['customer_ids'])
end
end
describe '#refresh_access_token!' do
it 'false if OAuth2 Fails' do
allow(user).to receive(:access_token) { true }
allow(user).to receive(:refresh_access_token!) { false }
allow(user).to receive(:result).and_raise(OAuth2::Error)
expect(user.refresh_access_token!).to be_falsey
end
it 'false if refresh fails' do
allow(user).to receive(:access_token) { true }
allow(user).to receive(:refresh_access_token!) { false }
expect(user.refresh_token!).to be_falsey
end
it 'true if new token' do
allow(user).to receive(:access_token) { true }
allow(user).to receive(:refresh_access_token!) { true }
expect(user.refresh_token!).to be_truthy
end
it 'true when refreshed' do
auth_token = OpenStruct.new(token: FFaker::Lorem.characters(50),
refresh_token: FFaker::Lorem.characters(50),
expires_at: 5.days.from_now)
allow(user).to receive_message_chain('access_token.refresh!') { auth_token }
expect(user.refresh_access_token!).to be_truthy
end
end
describe '#refresh_token!' do
it 'false if no access token' do
allow(user).to receive(:access_token) { false }
expect(user.refresh_token!).to be_falsey
end
it 'false if refresh fails' do
allow(user).to receive(:access_token) { true }
allow(user).to receive(:refresh_access_token!) { false }
expect(user.refresh_token!).to be_falsey
end
it 'true if new token is saved' do
allow(user).to receive(:access_token) { true }
allow(user).to receive(:refresh_access_token!) { true }
expect(user.refresh_token!).to be_truthy
end
end
describe '#token expired?' do
it 'true if valid' do
expect(user.token_expired?).to be_falsey
end
it 'false if expired' do
user.token_expires_at = 10.days.ago
expect(user.token_expired?).to be_truthy
end
end
end
更新
我将当前规范更改为:
it 'false if OAuth2 Fails' do
allow(OAuth2::AccessToken).to receive(:access_token) { Class.new }
allow(OAuth2::AccessToken).to receive_message_chain('access_token.refresh!') { raise OAuth2::Error.new('ERROR') }
binding.pry
end
但是,现在我收到以下错误:
WebMock::NetConnectNotAllowedError: Real HTTP connections are disabled. Unregistered request..
看来关键是这里的第二行:
def refresh_access_token!
result = access_token.refresh!
store_token(result)
save
rescue OAuth2::Error
false
end
所有其他测试存根 access_token
。如果您有一个调用真实方法的测试,它将覆盖 access_token
、client
、strategy
和 settings
.
现在 strategy
、settings
和 client
都很无聊:前两个基本上只是常量。 client
仅仅通过初始化它并没有做任何事情。所以打电话给那些应该没什么大不了的。只剩下 access_token
。你可以看到它初始化了一个 OAuth2::AccessToken
,它的代码是 on Github。初始化程序也很无聊。它只是保存输入供以后使用。
所以我会存根它的 refresh!
方法:一次给 return 一个看起来有效的刷新令牌,一次引发一个 OAuth2::Error
。您可以使用 expect_any_instance_of
来做到这一点。如果这让你感到不安,你也可以存根 :new
本身,并拥有它 return 你自己的假对象:
o = expect(OAuth2::AccessToken).to receive(:new) { Object.new }
expect(o).to receive(:refresh!) { raise OAuth2::Error.new("something here") }
看起来构建一个 OAuth2::Error
可能有点麻烦,因为它 takes a request object,但我没有看到那里有什么太复杂的东西,只是乱七八糟。
那应该会给你 100% 的覆盖率!
(代表问题作者发布解决方案).
现在已经解决了。
describe '#refresh_access_token!' do
it 'false if OAuth2 Fails' do
response = OpenStruct.new(error: 'ERROR')
allow(OAuth2::AccessToken).to receive_message_chain(:new, :refresh!) { raise OAuth2::Error.new(response) }
expect(user.refresh_token!).to be_falsey
end
it 'true if new token' do
allow(OAuth2::AccessToken).to receive_message_chain(:new, :refresh!) { @auth_token }
expect(user.refresh_token!).to be_truthy
end
end
存根令牌如下所示:
@auth_token = OpenStruct.new(token: FFaker::Lorem.characters(50),
refresh_token: FFaker::Lorem.characters(50),
expires_at: 5.days.from_now)
在研究了 Paul Jungwirth 发布的概念后,将 gem 中的方法存根阻止了 Webmock 警报的触发(如预期的那样),我可以正确触发加注。加注也必须与 gem 的响应设置相匹配。