2019年12月15日

pythonのunittestのpatchが分かりにくい

pythonのunittestのpatchを使用してテストを書いていた。
その中でうまくpatchできない場面があったので、残しておく。

起こったこと


patchで戻り値を変更しようとしても変更できなかった。
どうもpatchのtargetの指定が間違っているらしい。
何度やってもpatchで指定した値ではなく、正しい値が戻ってきた。
書いていたコードは以下のような感じ。

ディレクトリ構成
sample ├─ sample_dir_1 │ └─ sample1.py │ ├─ sample_dir_2 │ └─ sample2.py │ └─ tests └─ tests_sample1.py

sample1.py
from sample_dir_2.sample2 import add class Sample1: def call_add(self): return add(1, 2)

sample2.py
def add(a, b): return a + b

tests_sample1.py
from unittest import TestCase from unittest.mock import patch from sample_dir_1.sample1 import Sample1 class TestSample1(TestCase): def test_call_add(self): with patch(target='sample_dir_2.sample2.add', return_value=10) as p: sample1 = Sample1() actual = sample1.call_add() self.assertEqual(actual, 10)

この状態でtestを動かすと
AssertionError: 3 != 10
となる。
patchのtargetでpatch対象のパスを直接指定してもうまく動かないことが判明した。

解決方法

patchのtargetを以下のようにしたところ動いた。
target='sample_dir_1.sample1.add

pythonではmoduleがimportされた時点で元のmoduleから切り離され、import先の持ち物となるとのこと。
そのためsample1.pyにimportされたaddメソッドという意味で、sample_dir_1.sample1.addと指定する必要があった。

結論

pythonのimportの仕組みについて理解していれば、当然なのかもしれないが、結構嵌って時間を使ってしまった。
pythonのモジュールに関する理解をもっと深めたいと思う。

参考

https://note.crohaco.net/2015/python-mock/

0 件のコメント:

コメントを投稿