模拟与 __init__.py 模块混淆

Mocking confused with __init__.py module

我目前正在尝试使用 mock 来测试包。当我使用 __init__.py

在不同的目录中构建我的 python 模块时,Mock 似乎不喜欢它

我的文件树如下:

.\pkg
  |_ module
       |_ __init__.py
       |_ module.py
  |_ tests
       |_ __init__.py
       |_ test_basic.py

当我尝试使用以下单元测试模拟 filesize 中的方法时:

@mock.patch('module.os')
def test_filesize(self, mock_os):
    class file_info:
        st_size = 1000

    mock_os.path.isfile.return_value = True
    mock_os.stat.return_value = file_info

    output = self.response.file_size("filename")

我收到错误回溯:

======================================================================
ERROR: test_filesize (__main__.cl_test_build_search_url)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "C:\Python36\lib\site-packages\mock\mock.py", line 1297, in patched
    arg = patching.__enter__()
  File "C:\Python36\lib\site-packages\mock\mock.py", line 1369, in __enter__
    original, local = self.get_original()
  File "C:\Python36\lib\site-packages\mock\mock.py", line 1343, in get_original
    "%s does not have the attribute %r" % (target, name)
AttributeError: <module 'module' from 'C:\Users\username\work\open_source\pkg\module\__init__.py'> does not have the attribute 'os'

我已经在 module.py 中导入了 os 模块,但我认为它变得很混乱,因为 __init__.py 混淆了解释器?

我查看了可用的 mock.patch 个参数并且

@mock.patch('module.os', create = True)

允许代码 运行 但 os 根本不会被嘲笑,并且 os.path.isfileos.stat 在 [=40] 期间不会被覆盖=] 时间.

尝试改变这个:

@mock.patch('module.os', create = True)

对此:

# module(directory) module(module.py)
@mock.patch('module.module.os', create = True)

我不擅长解释,这里是 mock.py 解释的摘要:

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.

我想对@Gang 的回答再补充一点,因为这让我很生气。由于上面的示例名称,这会有点混乱,但是...

上面的例子:

.\pkg
  |_ module
       |_ __init__.py
       |_ module.py
  |_ tests
       |_ __init__.py
       |_ test_basic.py

假设在 pkg.module.module 中你有一个名为 module 的 class(与 python 文件名相同)

module.py

from time import time

class module:
    pass

在你的 pkg.module __init__.py 中你会做类似

from .module import module

__all__ = (
    "module",
)

如果您想在 module.py 中修补 time

mock.patch("pkg.module.module.time", ...)

Mock 将通过 __init__.py 得到 confused/blocked 并给你一个像

这样的错误
E AttributeError: <class 'pkg.module.module.module'> does not have the attribute 'time'

我必须更改文件名或 class。或者甚至只是改变大小写,在上面的例子中。

from time import time

class Module:
    pass

init.py

from .module import Module

__all__ = (
    "Module",
)