pytestのmonkeypatchで少々はまった話
2022-04-20
pytestのmonkeypatchで少々はまった話
pythonのテストツールpytestのモック機能である便利なmonkeypatchとやらを使ってみた。
参考:公式ドキュメント(How to monkeypatch/mock modules and environments)
monkeypathのテストで、「TypeError: ‘int’ object is not callable」というエラーがでいて、
このエラー文でググると、たくさんヒットするが、「”int”が変数として指定されてしまっているからターミナルを再起動しよう」とかの解決策がヒットし、
今回のケースにマッチしないので、はまっていた。
結果として、monkeypatchの第三引数は、直接指定ではなく、別メソッドの返り値から持ってくることで解決した。
(理由はよくわからず、、)
Contents
検証対象のクラス
% cat myclass.py class MyClass: def func_main(self) -> int: return 1 def func_add(self) -> int: return self.func_main() + 2
NGテストコード
% cat test_myclass_ng.py from myclass import MyClass class TestMyClass: def test_my_class(self, monkeypatch): monkeypatch.setattr(MyClass, 'func_main', 2) assert MyClass().func_add() == 4
実行結果
「TypeError: ‘int’ object is not callable」というエラーが出ている
% pytest test_myclass_ng.py ========================================================== test session starts ========================================================== platform darwin -- Python 3.9.1, pytest-7.1.1, pluggy-1.0.0 rootdir: /Users/yoshi/monkeypatch_work collected 1 item test_myclass_ng.py F [100%] =============================================================== FAILURES ================================================================ _______________________________________________________ TestMyClass.test_my_class _______________________________________________________ self = <test_myclass_ng.TestMyClass object at 0x101bbbcd0>, monkeypatch = <_pytest.monkeypatch.MonkeyPatch object at 0x101bbba00> def test_my_class(self, monkeypatch): monkeypatch.setattr(MyClass, 'func_main', 2) > assert MyClass().func_add() == 4 test_myclass_ng.py:8: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = <myclass.MyClass object at 0x101bbb6a0> def func_add(self) -> int: > return self.func_main() + 2 E TypeError: 'int' object is not callable myclass.py:8: TypeError ======================================================== short test summary info ======================================================== FAILED test_myclass_ng.py::TestMyClass::test_my_class - TypeError: 'int' object is not callable =========================================================== 1 failed in 0.04s ===========================================================
OKテストコード
% cat test_myclass.py from myclass import MyClass class TestMyClass: def dummy(self): return 2 def test_my_class(self, monkeypatch): monkeypatch.setattr(MyClass, 'func_main', self.dummy) assert MyClass().func_add() == 4
実行結果(成功!)
% pytest test_myclass.py ========================================================== test session starts ========================================================== platform darwin -- Python 3.9.1, pytest-7.1.1, pluggy-1.0.0 rootdir: /Users/yoshi/monkeypatch_work collected 1 item test_myclass.py . [100%] =========================================================== 1 passed in 0.01s ===========================================================