こしごぇ(B)

旧:http://d.hatena.ne.jp/koshigoeb/

S3 を使った実装のテストを fake-s3 を使って書いてみる

fakes3 (fake-s3) という gem を使うと、S3 のダミーサーバ(webrick)が使えるようになるとのこと。

サーバプロセスの管理をどうするのが今っぽいのか分からず、ググって得られた情報を元に、glint という gem を使ってみることに。

before(:suite) で glint に fakes3 の面倒を見てもらう。 after(:suite) は、fakes3 に渡した一時ディレクトリの後始末を行うのみ。

# spec/support/fakes3.rb
require 'tmpdir'
require 'glint'

RSpec.configure do |config|
  config.before :suite do
    rootdir = Dir.mktmpdir
    server = Glint::Server.new(nil, signals: [:INT]) do |port|
      exec "bundle exec fakes3 -p #{port} -r #{rootdir}", err: '/dev/null'
      exit 0
    end
    server.start

    Glint::Server.info[:fakes3] = {
      address: "127.0.0.1:#{server.port}",
      root: rootdir
    }
  end

  config.after :suite do
    if Dir.exists? Glint::Server.info[:fakes3][:root]
      FileUtils.remove_entry_secure(Glint::Server.info[:fakes3][:root])
    end
  end
end

ついでに、テスト実行中に万が一誤って本当の S3 に繋がらない様に webmock も入れてみる。

# spec/support/webmock.rb
require 'webmock/rspec'

WebMock.disable_net_connect!(:allow_localhost => true)

適当に example を書いて動作確認してみたけど、本当にこんな感じで良いのかはよく分かってない。

# spec/lib/example_spec.rb
require 'spec_helper'
require 'aws-sdk'

RSpec.describe Aws::S3 do
  let(:s3_client) do
    Aws::S3::Client.new(
      :access_key_id => 'YOUR_ACCESS_KEY_ID',
      :secret_access_key => 'YOUR_SECRET_ACCESS_KEY',
      :region => 'ap-northeast-1',
      :endpoint => "http://#{Glint::Server.info[:fakes3][:address]}/",
      :force_path_style => true)
  end

  before do
    Aws::S3::Resource.new(client: s3_client)
      .create_bucket(bucket: 'mybucket')
      .put_object(key: 'myobject', body: 'this is a pen.')
  end

  it 'バケットを作れること' do
    expect(Aws::S3::Resource.new(client: s3_client).bucket('mybucket'))
      .to be_an_instance_of Aws::S3::Bucket
  end

  it 'オブジェクトを作れること' do
    expect(s3_client.get_object(bucket: 'mybucket', key: 'myobject').body.read).to eq 'this is a pen.'
  end
end

S3 の API リクエストをスタブする方が良かったりするのだろうか?