Mocking dependencies in a Python module

Kellen Steffen
Bungalow Garage
Published in
2 min readMay 21, 2019

A few days ago, I set out to learn how to mock a dependency in a module I’m testing. Check out this lovely contrived three-file example:

# dependency.py
def thing_to_mock():
return 'mock me pls'

# module.py
from dependency import thing_to_mock
def thing_to_test():
return thing_to_mock()

# test_module.py
import pytest
import module
def test_thing_to_test():
module.thing_to_test()
# TODO: assert that thing_to_mock() gets called

At Bungalow, we use pytest-mock, which provides a thin wrapper around unittest.mock as a keyword arg called mocker to each test function.

I referred to the official mock docs, including the “Where to patch” section, to see how to mock a function in an imported dependency, but the examples only cover class mocking. However, mocking a dependency function on an imported module is as simple as providing the path to that function from the reference point of the test file.

Being new to Python, I did not know that imported modules and functions automatically become accessible attributes on the importing module, so I didn’t grok this until I came across this Stack Overflow question and accepted answer.

So the test becomes:

# dependency.py
def thing_to_mock():
return 'mock me pls'
# module.py
from dependency import thing_to_mock
def thing_to_test():
return thing_to_mock()
# test_module.py
import pytest
import module
def test_thing_to_test(mocker):
mock = mocker.patch('module.thing_to_mock')
module.thing_to_test()
mock.assert_called_once()

If the entire dependency is being imported, rather than using the from syntax, then the patch path changes:

# dependency.py
def thing_to_mock():
return 'mock me pls'
# module.py
import dependency
def thing_to_test():
return dependency.thing_to_mock()
# test_module.py
import pytest
import module
def test_thing_to_test(mocker):
mock = mocker.patch('module.dependency.thing_to_mock')
module.thing_to_test()
mock.assert_called_once()

If simply using mock, you can use the @patch decorator or call mock.patch() directly — the call is the same either way.

Addendum: Read the docs carefully

The Mock class, an instance of which is returned from mock.patch(), has several assertion methods, such as assert_called_once_with, assert_called_with, and assert_any_call. These methods may not do what you think!

  • assert_called_once_with asserts that the mock was called exactly once, and that the arguments match (not that the function was called once with the arguments provided, as I initially thought).
  • assert_called_once_with and assert_called_with only check the last call — this is the one that burned me. To check that the mock was called with a set of arguments at any point, use assert_any_call.

--

--

Kellen Steffen
Bungalow Garage

Backend Developer at @livebungalow . Avid Overwatch player, boulderer, and @warriors fan.