2

Given the following package structure:

# tree
.
├── setup.py
└── src
    └── package
        ├── bar.py
        ├── __init__.py
        └── test.py

And the following code:

# bar.py
from glob import glob

def baz():
    return glob('./*')

How can I correctly mock the call to glob in bar.baz when performing a relative import in test.py ? I've tried several approaches, including

# test.py
from unittest import mock
from .bar import baz

@mock.patch('package.bar.baz')
def test_baz(mock_baz):
    mock_baz.return_value = ['fizz']
    assert "fizz" in baz()


# pytest src/package/test.py
============================= test session starts ==============================
platform linux -- Python 3.7.1, pytest-4.0.0, py-1.7.0, pluggy-0.8.0
rootdir: /home/bewing/package, inifile:
plugins: cov-2.6.0, pylama-7.6.6, celery-4.2.1
collected 1 item

src/package/test.py F                                                    [100%]

=================================== FAILURES ===================================
___________________________________ test_baz ___________________________________

mock_baz = <MagicMock name='baz' id='140447846207104'>

    @mock.patch('package.bar.baz')
    def test_baz(mock_baz):
        mock_baz.return_value = ['fizz']
>       assert "fizz" in baz()
E       AssertionError: assert 'fizz' in ['./setup.py', './src']
E        +  where ['./setup.py', './src'] = baz()

src/package/test.py:7: AssertionError
=========================== 1 failed in 0.33 seconds ===========================

and

# test.py
from unittest import mock
from .bar import baz

    @mock.patch('.bar.baz')
    def test_baz(mock_baz):
        mock_baz.return_value = ['fizz']
        assert "fizz" in baz()

# pytest src/package/test.py
============================= test session starts ==============================
platform linux -- Python 3.7.1, pytest-4.0.0, py-1.7.0, pluggy-0.8.0
rootdir: /home/bewing/package, inifile:
plugins: cov-2.6.0, pylama-7.6.6, celery-4.2.1
collected 1 item

src/package/test.py F                                                    [100%]

=================================== FAILURES ===================================
___________________________________ test_baz ___________________________________

args = (), keywargs = {}, extra_args = [], entered_patchers = []
exc_info = (<class 'ValueError'>, ValueError('Empty module name'), <traceback object at 0x7effb803a4c8>)
patching = <unittest.mock._patch object at 0x7effbab69a58>

    @wraps(func)
    def patched(*args, **keywargs):
        extra_args = []
        entered_patchers = []

        exc_info = tuple()
        try:
            for patching in patched.patchings:
>               arg = patching.__enter__()

/home/bewing/.pyenv/versions/3.7.1/lib/python3.7/unittest/mock.py:1183:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
/home/bewing/.pyenv/versions/3.7.1/lib/python3.7/unittest/mock.py:1239: in __enter__
    self.target = self.getter()
/home/bewing/.pyenv/versions/3.7.1/lib/python3.7/unittest/mock.py:1409: in <lambda>
    getter = lambda: _importer(target)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

target = '.bar'

    def _importer(target):
        components = target.split('.')
        import_path = components.pop(0)
>       thing = __import__(import_path)
E       ValueError: Empty module name

/home/bewing/.pyenv/versions/3.7.1/lib/python3.7/unittest/mock.py:1092: ValueError
=========================== 1 failed in 0.47 seconds ===========================

1 Answer 1

2

You should patch glob not baz. Something like:

@mock.patch('package.bar.glob')
def test_baz(mock_glob):
    mock_glob.return_value = ['fizz']
    assert "fizz" in baz()
Sign up to request clarification or add additional context in comments.

1 Comment

Thank you for pointing out my obvious mistake! It turns out that I screwed up while anonymizing my actual issue, which was an __init__.py file present in src folder, which it turns out will also break relative imports for mock.patch somehow!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.