# Testing External Services
## 伺服器測試的四大主角
1. 客戶端(client)
2. 伺服器(server)
3. 假伺服器(fake server)
4. 調配器(adapter)

1. Smoke test是從客戶端到實際伺服器進行完整測試
1. Integration test主要測試內部程式碼
2. Client unit test完全切割外部API連結,專注測試內部程式
3. Adapter unit test則是驗證adapter stub的結果是否與service相同
## Introducing VCR
- 在第一次發出請求後,會將結果存為YAML檔案
- 模擬的是貼近真實狀態下的反應
- 可以定期錄製(更新)YAML檔
## Client Unit Tests
```ruby=
describe "avatars" do
let(:user) {create(:user)}
> let(:fake_adapter) { instance_double(AvatarAdapter) }
it "can get a twitter avatar URL" do
allow(AcatarAdapter).to receive(:new).with(user).and_return(fake_adapter)
allow(fake_adapter).to receive(:image_url).with(user).and_return("fake_url")
expect(user.avatar_url).to eq("fake_url")
expect(fake_adapter).to have_received(:image_url)
expect(AcatarAdapter).to have_received(:new)
end
end
```
### Why an Adapter?
- 如果程式中有多處地方需要發送請求到伺服器時
- 當發送請求時需要多筆數據與外部伺服器交流時
## Adapter Tests
```ruby=
require "rails_helper"
describe AvatarAdapter do
it "accurately receives image url", :vcr do
user = instance_double(User, twitter_handle: "noelrap")
adapter = AvatarAdapter.new(user)
url = "http://..."
expect(adapter.image_url).to eq(url)
end
end
```
## Testing for Error Cases
1. 直接將錯誤結果預錄下來,在每次測試時執行相關文件
2. 使用adapter test將特定方法(client端)stub後,預期回傳特定錯誤訊息
3. 使用adapter test將特定方法(client端)stub後,回傳非預期訊息
## Smoke Tests and VCR Options
```ruby=
VCR.use_cassette(re_record_interval: 7.days) #定期發出請求到外部伺服器
---------------------------------------------------------------------
VCR.configure do |c|
c.default_cassette_options = { record: #options }
end
options
:all -> 持續與外部連結並更新
:new_episodes -> 更新已經發送過請求的
:none -> 只會使用錄製好的YAML檔,絕不會發送請求
:once -> 使用錄製好的YAML檔,若有新的請求,會發送後錄製
---------------------------------------------------------------------
:match_requests_on -> 只針對特定參數進行比對
```