Jethro
Jethro

Reputation: 3369

How do you make a python mock work with both import A and from A import B

In python, mocking an object using

@patch('foo.bar')
def test_things(self, bar):
    bar.return_value= ...

requires that all tested classes use

import foo

and can not use

from foo import bar

In the second case code under test uses the original object, as mock patches names rather than the function itself. This feels very brittle.

How do we write mocks which will work with both forms of import?

Upvotes: 0

Views: 131

Answers (1)

Mauro Baraldi
Mauro Baraldi

Reputation: 6575

Short answer: No

The principle of a mock is to mock one object. If you import the same object from different ways in you your code (which is somehow weird) you need to create a mock for each object.

Example:

import os
from os.path import isdir

from unittest.mock import patch

>>> with patch('os.path') as mock_os_path:
...     mock_os_path.isdir.return_value = "Hello"
...     mocked_res = os.path.isdir("./")
...     res = path.isdir("./")
...     print("mocked_res)
...     print(res)
... 
Hello
True

According to docs

target should be a string in the form 'package.module.ClassName'. The target is imported and the specified object replaced with the new object, so the target must be importable from the environment you are calling patch() from. The target is imported when the decorated function is executed, not at decoration time.

Upvotes: 1

Related Questions