Python – Mocking Functions Using Python Mock

mockingpythonunit testing

I am trying to Mock a function (that returns some external content) using the python mock module.

I'm having some trouble mocking functions that are imported into a module.

For example, in util.py I have

def get_content():
  return "stuff"

I want to mock util.get_content so that it returns something else.

I am trying this:

util.get_content=Mock(return_value="mocked stuff")

If get_content gets invoked inside another module, it never actually seems to return the mocked object. Am I missing something in terms of how to use Mock?

Note that if I invoke the following, things work correctly:

>>> util.get_content=Mock(return_value="mocked stuff")
>>> util.get_content()
"mocked stuff"

However, if get_content is called from inside another module, it invokes the original function instead of the mocked version:

>>> from mymodule import MyObj
>>> util.get_content=Mock(return_value="mocked stuff")
>>> m=MyObj()
>>> m.func()
"stuff"

Contents of mymodule.py

from util import get_content

class MyObj:    
    def func():
        get_content()

So I guess my question is – how do I get invoke the Mocked version of a function from inside a module that I call?

It appears that the from module import function may be to blame here, in that it doesn't point to the Mocked function.

Best Answer

I think I have a workaround, though it's still not quite clear on how to solve the general case

In mymodule, if I replace

from util import get_content

class MyObj:    
    def func():
        get_content()

with

import util

class MyObj:    
    def func():
        util.get_content()

The Mock seems to get invoked. It looks like the namespaces need to match (which makes sense). However, the weird thing is that I would expect

import mymodule
mymodule.get_content = mock.Mock(return_value="mocked stuff")

to do the trick in the original case where I am using the from/import syntax (which now pulls in get_content into mymodule). But this still refers to the unmocked get_content.

Turns out the namespace matters - just need to keep that in mind when writing your code.