環境
やりたいこと
Rubyを使ってS3とか扱うこと全然あると思う。例えば以下はバケット一覧を取得して表示するコード
require 'aws-sdk-s3' client = Aws::S3::Client.new( region: 'ap-northeast-1' ) bucket_data = client.list_buckets.buckets bucket_data.each do |b| p b.name end
が、S3ないしはAWSはクラウドサービスなのでネットワークが入る。外部サービスをまたぐサービスを組み込んだコードのテストは結構厄介である。
これをなんとかしたい
方法1 非公式のモックライブラリを使う
例えばS3に限定した話だが、fake-s3というライブラリを使うとS3を振る舞うエンドポイントを作ることができる。
方法2localstack
もともとAtlassianが開発していたAWSのモックフレームワーク こっちは1と違ってフルスタックなので安心できる
懸念点としては今回みたいにピンポイントなモックを作るためだけにDockerを上げるべきなのかという点と引き継ぎ募集中!と書いてあって今後の開発が怪しいところ。。
方法3
公式が出しているモック機能を使う いわゆるstub
やり方
わりと簡単で手順は以下
- 同じクラスを
stub_responses: true
として生成する - stub_responsesで振る舞いを定義
あとは実際のレスポンス同様にクラスが振る舞ってくれる。以下はさっきのをstubで書き換えたバージョン
require 'aws-sdk-s3' client = Aws::S3::Client.new(stub_responses: true) client.stub_responses(:list_buckets, buckets: [{name:'hoge'}, {name:'piyo'}]) bucket_data = client.list_buckets.buckets bucket_data.each do |b| p b.name end
しゅごい
取得にはエラーがつきもの 実はstub_responsesには例外も渡すことができる
require 'aws-sdk-s3' client = Aws::S3::Client.new(stub_responses: true) client.stub_responses(:list_buckets, Aws::Sigv4::Errors::MissingCredentialsError) begin bucket_data = client.list_buckets.buckets bucket_data.each do |b| p b.name end rescue => e puts "#{e.class} #{e.message}" end
実行結果
Aws::Sigv4::Errors::MissingCredentialsError missing credentials, provide credentials with one of the following options: - :access_key_id and :secret_access_key - :credentials - :credentials_provider
当然オリジナルエラーも投げることができる
client = Aws::S3::Client.new(stub_responses: true) client.stub_responses(:list_buckets, StandardError.new("custom error"))
これ他のSESとかAWSサービスでもstub使えるっていうだから設計すごいなぁというお気持ち