Mockのpatchの勘違い

良くわからないけど唐突に意識高くなったので俺ブログ書くわ!!!ブログ書くわ!!! けど後2分くらいしかきっと持たない!!!早く書くんだ俺!!!2分後にはまた死んだ魚ような目になってしまうぞ!

という訳でPythonのMockで小一時間ハマったネタを書く。

前提

まずこんな感じで fuga.pyをimportして利用したhoge.pyをテストするhogetests.pyがあるとする。

# fuga.py
# -*- coding: utf-8 -*-

def piyo():
    return 'piyopiyo'
# hoge.py
# -*- coding: utf-8 -*-

from fuga import piyo

def hogecall():
    return piyo()

if __name__ == "__main__":
    print hogecall() # => piyopiyo
# hogetests.py
# -*- coding: utf-8 -*-

import random
import unittest
from mock import patch

class HogeTests(unittest.TestCase):

    def _getTargetFunc(self):
        from hoge import hogecall
        return hogecall

    def test_hogecall(self):
        hogecall = self._getTargetFunc()
        self.assertEqual(hogecall(), "piyopiyo")

if __name__ == '__main__':
    unittest.main()

やりたい事

ここで hogecallの中で読んでるpiyo()て関数をモック化したい。

def hogecall():
    return piyo() # <= コイツをモック化したい

間違った

最初はmock.patchを利用してこのように書いた

@patch('fuga.piyo', return_value="hogehoge")
def test_hogecall2(self, piyo):
     hogecall = self._getTargetFunc()
     self.assertEqual(hogecall(), "hogehoge")

だがこれはうまく行かず hogehogeが欲しいのにpiyopiyoばっかり帰ってきやがる。無茶しやがって。

正解

正解は patchに噛ます対象が、fuga.piyoではなく、hoge.piyoだった。patchで指定する時は、実際の処理で使われてる関数を置き換えるというものらしい。

@patch('hoge.piyo', return_value="hogehoge") #<=  × fuga.piyo   ○ hoge.piyo
def test_hogecall2(self, piyo):
     hogecall = self._getTargetFunc()
     self.assertEqual(hogecall(), "hogehoge")

余談

  • hogeとかpiyoとかhogehogeとかpiyopiyoとかもう書いてる本人も良くわからない。多分大体あってる