2018年7月13日金曜日

nifcloud-python-sdk で MagicMock を使う方法

概要

結構手こずったのでメモ
ポイントはどのモジュールに @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_sessioncreate_client もメソッドになります

とりあえずこれでテストするとレスポンスが以下のようにモックからのレスポンスに変わります

  • pipenv run python3 -m unittest test_nif.py
{'RequestId': 'xxxxxxx'}
.
----------------------------------------------------------------------
Ran 1 test in 0.001s

OK

最後に

Python3 の unittest.Mock は非常に便利なモックライブラリかなと思います
メソッドだけでなく属性やクラス全体をモック化することもできます
ただ、使い方が結構複雑なのでマスタするまでに多少の学習が必要かなと思います

0 件のコメント:

コメントを投稿