LoginSignup
6
3

More than 3 years have passed since last update.

pytest-mockのよく使う実装方法をまとめてみた

Last updated at Posted at 2020-10-21

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
6
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
3