概要
結構手こずったのでメモ
ポイントはどのモジュールに @patch
を当てるのかとメソッドをモック化するときは return_value
が必要な点かなと
環境
- macOS 10.13.5
- Python 3.6.5
テスト対象のコード
- vim nif.py
from nifcloud import session
class Nif(object):
def __init__(self):
self.cli = session.get_session().create_client(
"computing",
region_name="jp-east-1",
aws_access_key_id="xxxx",
aws_secret_access_key="xxxx"
)
def desc(self):
return self.cli.describe_security_groups()
これをテストします
普通にテストすると
- vim test_nif.py
import unittest
from nif import Nif
class TestNifClass(unittest.TestCase):
def test_desc(self):
n = Nif()
res = n.desc()
print(res)
if __name__ == '__main__':
unittest.main()
python3 -m unittest test_nif.py
で普通に describe_security_groups
がコールされます
モック化してみる
先ほどのテストをモック化して describe_security_groups
を呼ばないようにしてモックがレスポンスを返却するようにしてみます
import unittest
from nif import Nif
from unittest.mock import patch, MagicMock
class TestNifClass(unittest.TestCase):
# @patch('nif.session.get_session')
@patch('nifcloud.session.get_session')
def test_get(self, mock):
mock_res = MagicMock(return_value={'RequestId': 'xxxxxxx'})
mock.return_value.create_client.return_value.describe_security_groups = mock_res
n = Nif()
res = n.desc()
print(res)
if __name__ == '__main__':
unittest.main()
ポイントは 2 つでパッチを当てるのは @patch('nifcloud.session.get_session')
というのと describe_security_groups
のレスポンスをモックから返却させるために mock.return_value.create_client.return_value.describe_security_groups = mock_res
をしている点です
前者は @patch('nif.session.get_session')
でも動作します
後者はメソッドに対してモックを割り当てるため return_value
が必要です
get_session
も create_client
もメソッドになります
とりあえずこれでテストするとレスポンスが以下のようにモックからのレスポンスに変わります
pipenv run python3 -m unittest test_nif.py
{'RequestId': 'xxxxxxx'}
.
----------------------------------------------------------------------
Ran 1 test in 0.001s
OK
最後に
Python3 の unittest.Mock は非常に便利なモックライブラリかなと思います
メソッドだけでなく属性やクラス全体をモック化することもできます
ただ、使い方が結構複雑なのでマスタするまでに多少の学習が必要かなと思います