コントローラのテストをする際に、logger出力のテスト方法につまったので、備忘録として残します。他にいい方法があれば教えていただけると幸いです。
バージョン
Rails 6.1.5
実装方法
適当なアクションに遷移した時にlogを吐く場面を想定します。
class XXXController < ApplicationController
def index
logger.info "通ったで" #ここを検出したい
end
end
ログの内容をテストします。
# stubを使用するために必要
require 'minitest/mock'
# 略
test 'logger.info を出力' do
http_method = lambda { get staffs_path }
logs = get_logs(http_method)
expected_message = "通ったで"
# logsのなかに期待するlogがあるかどうかでassert
assert(logs.includes?(expected_message))
end
# 略
# アクション内で発生した複数のlogを配列として返す
# ①アクション内でinfoが呼ばれる
# ②infoがstackに置き換わる
# ③log_arrayにloggerの内容が格納される。
# ①-③の繰り返し
def get_logs(http_method)
log_array= []
stack= proc { |log_arg|
log_array.push(log_arg)
}
# stubメソッドにより、infoが呼び出される際に、処理がstackに置き換わる
Rails.logger.stub(:info, stack) do
http_method.call
end
log_array
end
備考
railsではアクションに遷移した際に以下のように複数のlogを吐いているため、「想定されるlogがあればテストに成功」という方法をとりました。
nil
"Processing by XXXController#index as HTML"
nil
"通ったで"
nil
また、http_method
の中身は以下のようにparams
を渡すことデータの更新時のテストにも使えそうです。
lambda { post login_path, params: { session:
{ email: 'sample@sample.com_1',
password: 'password' }}
}