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

Question:

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

Asked By: zalun

||

Answers:

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.

Answered By: brandizzi

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()
Answered By: number5

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).

Answered By: Cédric Julien
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.