我想模拟自定义设计策略,以在我的功能规范中验证用户。为了将请求存根到第三方应用程序,我正在使用WebMock,实现如下:
spec/utility/stub_methods.rb
def stub_aware_auth(creds, returns_token, _valid)
stub_request(:post, "http://example.com/oauth/token").
with(body: {"grant_type" => "password", "password" => creds.password, "username" => creds.email},
headers: {'Accept' => '*/*', 'Accept-Encoding' => 'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'Content-Type' => 'application/x-www-form-urlencoded'}).
to_return(status: 200, body: {'access_token' => returns_token, 'token_type' => 'bearer', 'expires_in' => 1200}.to_json, headers: {})
end
在规范中称为:
context 'AWARxE authenticated user' do
before do
stub_aware_auth(creds, return_token, valid)
end
let(:creds) do
OpenStruct.new(email: 'physiciansreallyshouldonlyautoauth@example.com', password: "Ican'tb3li3v3itsn0tbutt3r")
end
let(:return_token) { SecureRandom.hex(32) }
let(:valid) { true }
# other logic (...)
end
spec_helper.rb
WebMock.disable_net_connect!(allow_localhost: true)
它的工作原理非常令人惊讶,因为如果在一个测试示例中,它必须使用stub_aware_auth
两次,第一个请求返回定义的结果,但第二个请求抛出错误:
WebMock::NetConnectNotAllowedError: Real HTTP connections are disabled. Unregistered request: POST http://example.com/oauth/token with body 'grant_type=password&password=Ican%27tb3li3v3itsn0tbutt3r&username=PHYSICIANSREALLYSHOULDONLYAUTOAUTH%40EXAMPLE.COM' with headers {'Accept'=>'*/*', 'Accept-Encoding'=>'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'Content-Type'=>'application/x-www-form-urlencoded', 'User-Agent'=>'Faraday v0.12.1'}
You can stub this request with the following snippet:
stub_request(:post, "http://example.com/oauth/token").
with(body: {"grant_type"=>"password", "password"=>"Ican'tb3li3v3itsn0tbutt3r", "username"=>"PHYSICIANSREALLYSHOULDONLYAUTOAUTH@EXAMPLE.COM"},
headers: {'Accept'=>'*/*', 'Accept-Encoding'=>'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'Content-Type'=>'application/x-www-form-urlencoded', 'User-Agent'=>'Faraday v0.12.1'}).
to_return(status: 200, body: "", headers: {})
registered request stubs:
stub_request(:get, "http://example.com/api/v1/user").
with(headers: {'Authorization'=>'Bearer dc2dcf4c5b47ffcfea28c26490ed2a0e2580f152dfb18dbfc97670028d24ecaa'})
stub_request(:post, "http://example.com/oauth/token").
with(body: {"grant_type"=>"password", "password"=>"Ican'tb3li3v3itsn0tbutt3r", "username"=>"physiciansreallyshouldonlyautoauth@example.com"},
headers: {'Accept'=>'*/*', 'Accept-Encoding'=>'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'Content-Type'=>'application/x-www-form-urlencoded'})
这是令人惊讶的,因为WebMock.disable_net_connect!(allow_localhost: true)
是在spec_helper中定义的。
[编辑]
完整的失败示例(如果有帮助(:
spec/features/login_strategies_spec.rb
context 'AWARxE authenticated user' do
before do
stub_aware_auth(creds, return_token, valid)
end
let(:return_token) { SecureRandom.hex(32) }
let(:valid) { true }
context 'physician' do
let(:creds) do
OpenStruct.new(email: 'physiciansreallyshouldonlyautoauth@example.com', password: "Ican'tb3li3v3itsn0tbutt3r")
end
let(:user) { build(:physician) }
before do
stub_aware_user_info(user, 'Physician (MD, DO)', return_token, valid, 1)
end
# some other it block (...)
context 'case insensitive' do
let(:valid) { true }
let(:uppercase_email_creds) {
OpenStruct.new(email: creds.email.upcase, password: creds.password)
}
scenario 'logging in with upper case email' do
expect { subject }.to change(Login, :count)
logout
expect {
login(uppercase_email_creds)
}.to_not change(Login, :count)
expect(page).to have_current_path(name_search_registrants_url, url: true)
end
end
end
您正在创建的存根仍在原始creds
上,带有小写电子邮件。除非你真的调用了类似的东西,否则webmock不可能模拟呼叫
stub_aware_auth(uppercase_email_creds, return_token, valid)
如果你真的希望应用程序在正文中使用小写电子邮件进行调用,那么测试失败了,因为它应该失败,它使用大写电子邮件进行调用:
You can stub this request with the following snippet:
stub_request(:post, "http://example.com/oauth/token").
with(body: {..., "username"=>"PHYSICIANSREALLYSHOULDONLYAUTOAUTH@EXAMPLE.COM"},
...).
to_return(status: 200, body: "", headers: {})