0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Pythonのmockについての備忘録

Posted at

先日PythonのMockに悩まされまくったので備忘録を置いておきます。

とりあえず公式ドキュメント

[unittest.mock --- モックオブジェクトライブラリ]
(https://docs.python.org/ja/3/library/unittest.mock.html)
[unittest.mock --- 入門]
(https://docs.python.org/ja/3/library/unittest.mock-examples.html)

2時間ぐらい悩んだことが公式にさらっと書いてあった。
公式は偉大

requests.getをmockする

tori01.py
import requests

def get_qiita(url):
    response = requests.get(url)
    return response

urlでgetして返ってきたresponseを返すだけ

test_tori01.py
import unittest
from mock import Mock, patch

import tori01

class TestTori01(unittest.TestCase):

    @patch("tori01.requests.get")
    def test_get_response(self, requests_get):
        requests_get.return_value.status_code = 200

        res = tori01.get_response("mock.url")
        self.assertEqual(res.status_code, 200)

ステータスコードでアサーションチェック
今回これらのコードを土台とする

patch周り

tori01.pyrequestsがimportされているので
@patch("tori01.requests.get")でpatchされる

これがtori01.pyrequests.getがimportされていると
@patch("tori01.get")としないとpatchされない

tori01.py
# import requests から変更
from requests import get

def get_response(url):
    response = get(url)
    return response
test_tori01.py
import unittest
from mock import Mock, patch

import tori01

class TestTori01(unittest.TestCase):

    # @patch("tori01.requests.get") から変更
    @patch("tori01.get")
    def test_get_response(self, requests_get):
        requests_get.return_value.status_code = 200

        res = tori01.get_response("mock.url")
        self.assertEqual(res.status_code, 200)

`requests.get`ではなく、`requests`をmockしたい場合(どっちが正統なんだろうか)
test_tori01.py
import unittest
from mock import Mock, patch

import tori01

class TestTori01(unittest.TestCase):

    # @patch("tori01.requests.get") から変更
    # 引数の命名もrequests.get→requestsに変更
    @patch("tori01.requests")
    def test_get_response(self, requests):
        # requests_get.return_value.status_code = 200 から変更
        requests.get.return_value.status_code = 200

        res = tori01.get_response("mock.url")
        self.assertEqual(res.status_code, 200)

関数を呼び出す

呼び出された時の引数を確認することができる。

test_tori01.py
import unittest
from mock import Mock, patch

import tori01

class TestTori01(unittest.TestCase):

    @patch("tori01.requests.get")
    def test_get_response(self, requests_get):

        # mockを返す関数を作り、呼び出されるようにする。
        def requests_get_mock(url):
            return Mock(status_code = 200, url = url)

        requests_get.side_effect = requests_get_mock

        res = tori01.get_response("mock.url")
        self.assertEqual(res.status_code, 200)
        self.assertEqual(res.url, "mock.url")

こんな回りくどいことをしなくても`assert_called_with`でチェックできる。 他のassert系も色々ある
test_tori01.py
import unittest
from mock import Mock, patch

import tori01

class TestTori01(unittest.TestCase):

    @patch("tori01.requests.get")
    def test_get_response(self, requests_get):
        requests_get.return_value.status_code = 200

        res = tori01.get_response("mock.url")
        self.assertEqual(res.status_code, 200)
        requests_get.assert_called_with("mock.url") #追加

引数によって戻り値を変化
test_tori01.py
import unittest
from mock import Mock, patch

import tori01

class TestTori01(unittest.TestCase):

    @patch("tori01.requests.get")
    def test_get_response(self, requests_get):

        vals = {"mock.url":200, "error_mock.url":404}
        def requests_get_mock(val):
            return Mock(status_code = vals[val])

        requests_get.side_effect = requests_get_mock

        res = tori01.get_response("mock.url")
        res_error = tori01.get_response("error_mock.url")
        self.assertEqual(res.status_code, 200)
        self.assertEqual(res_error.status_code, 404)

例外を投げることもできる
test_tori01.py
import unittest
import requests
from mock import Mock, patch

import tori01

class TestTori01(unittest.TestCase):

    @patch("tori01.requests.get")
    def test_get_response(self, requests_get):

        # side_effectに例外クラスを設定すれば例外が投げられる
        requests_get.side_effect = requests.HTTPError

        with self.assertRaises(requests.HTTPError):
            tori01.get_response("mock.url")

追記したり、その2を書くかも

MagicMockとか…

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

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?