How to mock a function defined in a module of a package?

PythonMocking

Python Problem Overview


I've got a following structure:

|-- dirBar
|   |-- __init__.py
|   |-- bar.py
|-- foo.py
`-- test.py

bar.py

def returnBar():
    return 'Bar'

foo.py

from dirBar.bar import returnBar

def printFoo():
    print returnBar()

test.py

from mock import Mock

from foo import printFoo
from dirBar import bar

bar.returnBar = Mock(return_value='Foo')

printFoo()

the result of python test.py is Bar.

How to mock the printBar to make it return Foo so that printFoo will print it?

EDIT: Without modifying any other file that test.py

Python Solutions


Solution 1 - Python

I'm guessing you are going to mock the function returnBar, you'd like to use patch decorator:

from mock import patch

from foo import printFoo

@patch('foo.returnBar')
def test_printFoo(mockBar):
    mockBar.return_value = 'Foo'
    printFoo()

test_printFoo()
    

Solution 2 - Python

Just import the bar module before the foo module and mock it:

from mock import Mock

from dirBar import bar
bar.returnBar = Mock(return_value='Foo')

from foo import printFoo

printFoo()

When you are importing the returnBar in foo.py, you are binding the value of the module to a variable called returnBar. This variable is local so is put in the closure of the printFoo() function when foo is imported - and the values in the closure cannot be updated by code from outiside it. So, it should have the new value (that is, the mocking function) before the importing of foo.

EDIT: the previous solution workis but is not robust since it depends on ordering the imports. That is not much ideal. Another solution (that occurred me after the first one) is to import the bar module in foo.py instead of only import the returnBar() function:

from dirBar import bar

def printFoo():
    print bar.returnBar()

This will work because the returnBar() is now retrieved directly from the bar module instead of the closure. So if I update the module, the new function will be retrieved.

Solution 3 - Python

Another way to deal with those case is to use some dependency injection.

An easy way to do it in python is to use the magical **kwargs :

foo.py

from dirBar.bar import returnBar

def printFoo(**kwargs):
    real_returnBar = kwargs.get("returnBar", returnBar)
    print real_returnBar()

test.py

from mock import Mock

from foo import printFoo
from dirBar import bar

mocked_returnBar = Mock(return_value='Foo')

printFoo(returnBar=mocked_returnBar)

this will lead to a more testable code (and increase modularity/reusability).

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionzalunView Question on Stackoverflow
Solution 1 - Pythonnumber5View Answer on Stackoverflow
Solution 2 - PythonbrandizziView Answer on Stackoverflow
Solution 3 - PythonCédric JulienView Answer on Stackoverflow