きっかけ
今回はjsonファイルを読み込んで、そのjsonデータを保存する実装をしていました。
RSpecも書くということでしたが(当たり前やん!)、jsonデータを読み込む時のやり方に少し躓いたので、まとめてみようと思います。
実装内容
という感じ。
RSpecを書くときは、外部ファイルサービスへのアクセスはしないでモックと/spec/fixtureに置いたファイルで対応する。
そもそもRSpec初心者の私には、 外部ファイルサービスにアクセスしないでテストする
というのをどうしたらいいのかから悩む事になった。
モックを使うことを知る
こちらの記事を参考に直接外部ファイルサービスにアクセスしない方法が見えてきました。
ここで私が使ったのは、1番よく使われるらしい double
メソッドと allow
メソッド。
jsonを読みにいく処理が走るときは、/spec/fixtureに置いたjsonファイルの中身を返すというように書きました。
例えば、こんな前提
- userに対するscoreが保存されているjsonデータが外部ファイルサービスのバケットにある
- バケットにコールするモジュールが
CallBucket
- データを保存する処理は
StoreJsonData
にかかれている CallBucket
はStoreJsonData
の中から呼ばれる- テストは
StoreJsonData
で保存されたsocreが正しいかを確認する sample.json
にはとあるuserのscore=3
というデータがあるとする
これをテスト書いてみる
let(:json_file) { Rack::Test::UploadedFile.new("#{Rails.root}#{file_path}", "application/json") } before(:each) do bucket = double('bucket') json_data = JSON.parse(File.read(json_file.path)) allow(CallBucket).to receive(:new).and_return(json_data) StoreJsonData.new.import(bucket) end context "sample data" do let(:file_path) { "/spec/fixtures/sample.json" } it "save" do expect(user.score).to eq 3 end end
詰まったところ
JSON.parse(data)
としていますが、最初は JSON.load(file)
としていて、rubocopにセキュリティ的によくないよ!と怒られました。
ただ、単純にJSON.parse(file)
ではだめで、一回オブジェクト化した状態で JSON.parse
を使わなければならないことに少し時間がかかりました。
before/afterはこんな感じ
before
json_data = JSON.load(json_file.path)
after
json_data = JSON.parse(File.read(json_file.path))
JSON.parse
にはファイルの中身をロードする処理はないので、事前にfile.readしてjson文字列として渡してあげないといけないということらしいです。
さいごに
まだまだRSpecは勉強中ですが、次からファイルの読み込みが必要なRSpecはすぐに書けそうです!
でも全体的にRSpecの知識が足りてないから、一回体系的にやりたいところ。。
時間を見つけてコツコツとキャッチアップできればと思います。