當在撰寫測試時,肯定會遇到是在處理外部服務(api)的事情。
正因為我也剛好使用了 coverage
這個 gem,來看看測試覆蓋率。
不管怎麼做,就是沒有頭緒,不知道怎麼在測試裡執行裡面的程式。
我們也必須確保這段程式沒有誤。
直到我用了 webmock
這個 gem,也就是今天的主角。
webmock
是用於在Ruby中對HTTP請求進行 stub 設置與期望的結果。它允許我們對HTTP請求進行stub,並設置和驗證對任何HTTP請求的期望。也能使用 Net::HTTP
當然也可以使用 HTTParty
當我們在 Rspec
使用 webmock
需要設定與讓我們通過禁用我們的測試套件來確保它們不能發出外部請求
1 2 3 4
|
require 'webmock/rspec' WebMock.disable_net_connect!(allow_localhost: true)
|
我設定了一個 UserService
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| class UserService def initialize(email) @email = email end
def user_profile HTTParty.get('https://demo.com/profile', query: { user: @email }, headers: { 'Content-Type': 'application/json' }) end
def add_new_user HTTParty.post('https://demo.com/new_user', body: { user: @user }, headers: { 'Content-Type': 'application/json' }) end end
|
這是用來模擬可以用 email
,來獲取使用者資料或是新增使用者的 service
接下來就可以開始撰寫我們的測試了
首先我們針對 #user_profile
這個 method
開始
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| require 'rails_helper'
RSpec.describe UserService do describe '#user_profile' do it 'Correct URI' do stub_request(:get, 'https://demo.com/profile').with( headers: { 'Content-Type': 'application/json' }, query: hash_including({ user: 'willy@gmail.com' }) ).to_return(body: { status: 200, name: 'willy', age: 18 }.to_json) resp = UserService.new('willy@gmail.com').user_profile result = JSON.parse(resp)
expect(result['status']).to eq(200) expect(result['name']).to eq('willy') expect(result['age']).not_to eq(30) end end end
|
我們把 uri
換成別的看看
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| it 'Wrong URI' do stub_request(:get, 'https://test.com/profile').with( headers: { 'Content-Type': 'application/json' }, query: hash_including({ user: 'willy@gmail.com' }) ).to_return(body: { status: 200, name: 'willy', age: 18 }.to_json) resp = UserService.new('willy@gmail.com').user_profile result = JSON.parse(resp)
expect(result['status']).to eq(200) expect(result['name']).to eq('willy') expect(result['age']).not_to eq(30) end
|
沒意外的話,在 run rspec 時,會得到下面的回應
1
| WebMock::NetConnectNotAllowedError
|
我們也可以stub_request(:post)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| describe '#add_new_user' do it 'create user success' do stub_request(:post, 'https://demo.com/new_user').with( headers: { 'Content-Type' => 'application/json' } ).to_return(body: { status: 200, message: 'ok' }.to_json) resp = UserService.new('willy@gmail.com').add_new_user result = JSON.parse(resp)
expect(result['status']).to eq(200) expect(result['message']).to eq('ok') end end end
|
結論:
stub_request
的 uri
必須跟原本的 get
or post
的 uri
一樣1 2 3
| 例如我在 `#user_profile` HTTParty.get('https://demo.com/profile') 那我 stub_request(:get, 'https://demo.com/profile') 就必須跟上面一樣,否則就會出現上面的 error
|
- 我們要確保我們的測試套件不會影響任何第三方服務。我們的測試應該獨立運行。
- 加速我們針對測試的撰寫
-W