Pythonで、unittest.mock.patchを使って定数を差し替える

小ネタです。

以前、 unittest.mock.patch を使ってデコレータを差し替えたことがありました。
Pythonで、unittest.mock.patchを使ってデコレータを差し替える - メモ的な思考的な

 
今回は、unittest.mock.patch を使って定数を差し替えてみます。

 
目次

 

環境

  • Python 3.7.5
  • pytest 5.3.1
    • テストランナーとしてのみ、使用

 

定数の差し替え

デコレータの時と同様、今回の定数の差し替えでも unittest.mock.patch() を使います。
https://docs.python.org/ja/3/library/unittest.mock.html#unittest.mock.patch

 
デコレータや関数の場合は、 side_effectreturn_value を使いました。

ただ、定数の場合は単にオブジェクトの差し替えだけのため、第2引数(もしくは new キーワード引数)で、差し替え後の値を渡してあげます。

 
たとえば、 target.py というファイルに、以下のようなプロダクションコードがあるとします。

DEBUG = True

def get_mode():
    return 'デバッグ' if DEBUG else 'プロダクション'

これに対し、定数 DEBUGFalse に差し替えたテストコードを書きたいとします。

 
この場合、

from target import get_mode
from unittest.mock import patch


@patch('target.DEBUG', False)
def test_production():
    actual = get_mode()
    assert actual == 'プロダクション'


@patch('target.DEBUG', new=False)
def test_production_with_new_keyword():
    actual = get_mode()
    assert actual == 'プロダクション'

とすることで、定数 DEBUG の値が TrueからFalseへと差し替わります。

 
また、もしテストの一時期だけDEBUGの値を差し替えたいという場合には、patchをwith文とともに使います。

def test_patch_using_with():
    # with文の中では、定数の値がFalseになる
    with patch('target.DEBUG', False) as p:
        actual1 = get_mode()
        assert actual1 == 'プロダクション'

    # with文を抜けると、定数の値がTrueに戻る
    actual2 = get_mode()
    assert actual2 == 'デバッグ'

 

その他参考

unit testing - How to patch a constant in python - Stack Overflow

 

ソースコード

Githubに上げました。ディレクトe.g._patch_constant が今回のものです。
https://github.com/thinkAmi-sandbox/python_mock-sample