pytest-mockの使い方を調べたのでメモ
今後も使いそうなユースケースを都度調べるのが面倒なのでまとめてみました。
pytestを調べてから1日で書いた記事なので色々過不足があると思いますが、もっと良い方法が見つかったら随時アップデートしていきたいと思います。
pytest、pytest-mockについて
pythonのテストコードを実装するときに使うライブラリの1つです。
詳細は公式ホームページを参照してください。
pytest
pytest-mock
説明に使うメソッド
下記のhogeメソッドをテスト対象とします。
from mailer import Mailer
# messagesの例
# ['1通目の本文', '2通目の本文']
def hoge(messages):
try:
# messagesの数だけメール送信
for message in messages:
has_error = Mailer.send(message)
if has_error:
# エラー発生時は1を返却
return 1
# 正常終了時は0を返却
return 0
except Exception as e:
# 例外発生時は2を返却
return 2
この記事を書いたときに使ったバージョンは下記の通りです。
- python 3.8.5
- pytest 6.1.1
- pytest-mock 3.3.1
Mailer.send
をモックに差し替える
test_hoge.py
from hoge import hoge
from mailer import Mailer
from unittest.mock import call
def test_hoge(mocker):
# Mailer.sendをモックに差し替える
mailer_mock = mocker.patch.object(Mailer, 'send')
messages = ['1通目の本文', '2通目の本文']
# 上記でMailer.sendをモックにしているのでhogeを実行しても本物のMailer.sendは実行されません
assert hoge(messages) == 0
呼び出し回数を検証したい
test_hoge.py
from hoge import hoge
from mailer import Mailer
from unittest.mock import call
def test_hoge(mocker):
# Mailer.sendをモックに差し替える
mailer_mock = mocker.patch.object(Mailer, 'send')
messages = ['1通目の本文', '2通目の本文']
assert hoge(messages) == 0
# Mailer.sendが2回呼ばれることを確認できます
assert mailer_mock.call_count == 2
呼び出されないことを検証したい
test_hoge.py
from hoge import hoge
from mailer import Mailer
from unittest.mock import call
def test_hoge(mocker):
# Mailer.sendをモックに差し替える
mailer_mock = mocker.patch.object(Mailer, 'send')
# messagesが空なのでMailer.sendは呼ばれないようにする
messages = []
assert hoge(messages) == 0
# Mailer.sendが呼ばれないことを検証
mailer_mock.assert_not_called()
パラメーターを検証したい
test_hoge.py
from hoge import hoge
from mailer import Mailer
from unittest.mock import call
def test_hoge(mocker):
# Mailer.sendをモックに差し替える
mailer_mock = mocker.patch.object(Mailer, 'send')
messages = ['1通目の本文', '2通目の本文']
assert hoge(messages) == 0
# 1回目は'1通目の本文'、2回目は'2通目の本文'がパラメーターで渡されて呼び出されていることが検証できます
mailer_mock.assert_has_calls([call('1通目の本文'), call('2通目の本文')])
戻り値を制御したい
test_hoge.py
from hoge import hoge
from mailer import Mailer
from unittest.mock import call
def test_hoge(mocker):
# side_effectに配列で戻り値のリストを渡します
# 呼び出されるごとに配列の先頭から順番に返却されます
# この例の場合、1回目はFalse、2回目はTrueが返却されます
mailer_mock = mocker.patch.object(Mailer, 'send', side_effect = [False, True])
messages = ['1通目の本文', '2通目の本文']
# 2回めのMailer.sendがTrueを返却するので戻り値1の検証ができます
assert hoge(messages) == 1
例外を発生させたい
test_hoge.py
from hoge import hoge
from mailer import Mailer
from unittest.mock import call
def test_hoge(mocker):
# side_effectに例外を指定します
# この例の場合、1回目はFalse、2回目は例外が発生します
mailer_mock = mocker.patch.object(Mailer, 'send', side_effect = [False, Exception('error')])
messages = ['1通目の本文', '2通目の本文']
# 2回めのMailer.sendが例外が発生するので戻り値2の検証ができます
assert hoge(messages) == 2