从相同的python模块模拟相对导入

时间:2019-02-13 22:36:34

标签: python mocking python-unittest

给出以下包结构:

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

以及以下代码:

# bar.py
from glob import glob

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

glob中执行相对导入时,如何正确模拟对bar.baz中的test.py的调用?我尝试了几种方法,包括

# 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 ===========================

# 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 个答案:

答案 0 :(得分:1)

您应该修补glob而不是baz。像这样:

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