関数のモックに例外を設定する方法について記載します。
それにはside_effectという属性を使用します。
下記の例ではpatchを利用しています。そちらの書き方について知りたい方は次の記事をご参照ください。【Python】unittest.mock.patchの使い方
結論
例えば、ZeroDivisionErrorを返すモックを作成する場合は次のように記述します。
@patch("モックにしたい関数へのパス")
def test_case_error_01(self, mock_01):
mock_01.side_effect = ZeroDivisionError()
また、単なるExceptionの場合は次のように記述します。
@patch("モックにしたい関数へのパス")
def test_case_error_01(self, mock_01):
mock_01.side_effect = Exception()
except ZeroDivisionError as e:のようにeの値も設定したい場合は、以下のようにZeroDivisionErrorの引数に値を指定します。この例ではhogeとしています。
@patch("モックにしたい関数へのパス")
def test_case_error_01(self, mock_01):
mock_01.side_effect = ZeroDivisionError("hoge")
具体例
次のようなソースmain_process.pyがあり、unfinished()をモックにしてそれぞれの例外をテストしたいとする。
def unfinished():
return print("未完成の関数")
def execute():
try:
# モックにしてテストする
unfinished()
# 以下の例外をテストしたい
except KeyError as e:
print(f"エラー:{e}")
return "error_1"
except ZeroDivisionError as e:
print(f"エラー:{e}")
return "error_2"
except Exception as e:
print(f"エラー:{e}")
return "error_3"
if __name__ == "__main__":
execute()
例えばunfinished 関数からZeroDivisionErrorの例外が呼び出された場合のテストコードは次のようになります。
テスト対象のソース main_process.pyへのパスはwork.src.main_processとします。
import unittest
from unittest.mock import patch
from work.src import main_process
class test_main_process(unittest.TestCase):
@patch("work.src.main_process.unfinished")
def test_case_error_01(self, execute_mock):
# モックの設定
execute_mock.side_effect = ZeroDivisionError("hogehoge")
# テストの実行
result = main_process.execute()
self.assertEqual(result, "error_2")
if __name__ == "__main__":
unittest.main()
以下は実行結果です。
ZeroDivisionErrorをキャッチするとexecute関数からerror_2が返ってくる想定であり、予想通りの結果であったためOKが出力されています。
Testing started at 11:28 ...
エラー:hogehoge
Ran 1 test in 0.008s
OK
エラー:hogehogeの部分はモックのZeroDivisionErrorの引数にしていしたhogehogeがexcept ZeroDivisionError as e:のeのとして出力されています。