Search code examples
pythonunit-testingmockingmonkeypatching

Python monkeypatch doesn't patch function correctly


I'm trying to use monkeypatch to mock one public function but it doesn't seem to work for me.

Here's my file structure

myproject
  |-mrss
     |- feed_burner.py <- has get_feed()
     |- version_controller.py <- has get_version()
  |-tests
     |-feed_burner_tests.py

Here's my test

from mrss.feed_burner import get_feed
from _pytest.monkeypatch import monkeypatch


 def test_first_feed(self):
        mp = monkeypatch()
        mp.setattr(mrss.version_controller, 'get_version', lambda env: 7)
        mrss_feed = get_feed(env=get_config())
        root = ET.fromstring(mrss_feed)

        self.assertEquals(21, len(programmes))

And this is my get_feed function

from mrss.version_controller import get_version

def get_feed(env=os.environ):
    uploader = Uploader(env=env)
    folder = env.get('S3_FOLDER')

    version = get_version(env)
    print version.isdigit()
    print 'version is {v}'.format(v=str(version))
    if not version or not version.isdigit():
        return ''

And all I got for get_version is empty string

False
version is

I tried with this but no luck

with patch('mrss.feed_burner.get_feed.mrss.version_controller.get_version', new=lambda env: 7):
    mrss_feed = get_feed(env=get_config())
    root = ET.fromstring(mrss_feed)

    programmes = root.findall('programme')

    self.assertEquals(21, len(programmes))

Solution

  • In your test function,

    from mrss.feed_burner import get_feed
    from _pytest.monkeypatch import monkeypatch
    
    
    def test_first_feed(self):
        mp = monkeypatch()
        mp.setattr(mrss.version_controller, 'get_version', lambda env: 7)
        mrss_feed = get_feed(env=get_config())
        root = ET.fromstring(mrss_feed)
    
        self.assertEquals(21, len(programmes))
    

    the function object referenced by get_feed doesn't call mrss.version_controller.get_version, which is the reference used by your test module. It really calls mrss.feed_burner.mrss.version_controller.get_version, which is what you need to monkey patch. (get_feed has its own reference to its module scope, which is distinct from the reference in the test module.)