【Python】単体試験 / pytest ~ 基本編 / pytest-mock ~

■ はじめに

https://dk521123.hatenablog.com/entry/2020/12/13/224810
https://dk521123.hatenablog.com/entry/2021/11/24/163751

の続き。

PyTest の Mock について、学ぶ。

目次

【1】環境設定
【2】サンプル
 例1:戻り値をMock化 - mocker.patch
 例2:例外を発生させる - mocker.patch / side_effect
 例3:処理を置き換える - mocker.Mock() / mocker.patch.object

【1】環境設定

pip install pytest pytest-mock

poetry の場合

poetry add -D pytest-mock

【2】サンプル

フォルダ構成

project
 + project_a
    + hello.py
 + tests
    + test_hello.py

./project_a/hello.py (テスト対象)

import requests

class Hello:
  def __init__(self):
    self._request = requests

  def get(self, url):
    try:
      response = self._request.get(url)
      return response.status_code
    except Exception:
      return -1

例1:戻り値をMock化 - mocker.patch

./tests/test_hello.py (テストコード)

from project_a.hello import Hello

@pytest.fixture(scope='function')
def hello():
  hello = Hello()
  return hello


class TestHello:
  def test_get(self, mocker, hello):
    mocker.patch("project_a.hello.Hello.get", return_value=200)
    assert hello.get("http://localhost:8080/xxxx") == 200

実行および出力結果

# オプション「-s」:print(標準出力)を出力
project/project_a>pytest -q ./tests/test_hello.py -s

例2:例外を発生させる - mocker.patch / side_effect

./tests/test_hello.py (テストコード一部抜粋)

# 下記、以外は、例1と同じ
class TestHello:
  def test_get(self, mocker, hello):
    # ★「side_effect=Exception('Error')」で処理を置き換える★
    mocker.patch("requests.get", side_effect=Exception('Error'))
    assert hello.get("http://localhost:8080/xxxx") == -1

例3:処理を置き換える - mocker.Mock() / mocker.patch.object

./tests/test_hello.py (テストコード一部抜粋)

# 下記、以外は、例1と同じ
import requests

class TestHello:
  def test_get(self, mocker, hello):
    response_mock = mocker.Mock()
    response_mock.status_code = 300
    mock_requests_get = mocker.patch.object(
      requests, "get", return_value=response_mock)
    assert hello.get("http://localhost:8080/xxxx") == 300
    # requests.get()が引数'http://localhost:8080/xxxx'で1回呼ばれたことの検証
    mock_requests_get.assert_called_once_with("http://localhost:8080/xxxx")

参考文献

https://webbibouroku.com/Blog/Article/pytest-mock
https://qiita.com/East-Da/items/211d06359a7573116eb7
https://webbibouroku.com/Blog/Article/pytest-mock

関連記事

単体試験 / pytest ~ 入門編 ~
https://dk521123.hatenablog.com/entry/2020/12/13/224810
単体試験 / pytest ~ 基本編 / Fixture ~
https://dk521123.hatenablog.com/entry/2021/11/24/163751