【问题标题】:Mocking confused with __init__.py module模拟与 __init__.py 模块混淆
【发布时间】:2018-09-26 19:09:09
【问题描述】:

我目前正在尝试使用 mock 来测试一个包。当我使用 __init__.py 在不同目录中构建我的 python 模块时,Mock 似乎不喜欢它

我的文件树如下:

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

当我尝试使用以下单元测试模拟文件大小中的方法时:

@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 在运行时不会被覆盖。

【问题讨论】:

    标签: python unit-testing mocking python-unittest


    【解决方案1】:

    我想在@Gang 的回答中添加更多内容,因为这让我很生气。由于上面的示例名称,这会有点令人困惑,但是...

    上面的例子:

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

    假设在pkg.module.module 中有一个名为module 的类(与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 混淆/阻止,并给你一个类似的错误

    E AttributeError: <class 'pkg.module.module.module'> does not have the attribute 'time'
    

    我不得不更改文件或类的名称。或者甚至只是改变大小写,在上面的例子中。

    from time import time
    
    class Module:
        pass
    

    init.py

    from .module import Module
    
    __all__ = (
        "Module",
    )
    
    

    【讨论】:

      【解决方案2】:

      尝试改变这一点:

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

      到这里:

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

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

      target 应该是'package.module.ClassName' 形式的字符串。这 target 被导入并且指定的对象被替换为new 对象,因此 target 必须可以从您所在的环境中导入 打电话给patch。装饰函数时导入目标 被执行,而不是在装饰时。

      【讨论】:

      • 我以为我已经导入了module.py 为什么还要再给出完整路径?
      • 你必须模拟它在另一个脚本中的初始化位置,因此你必须提供完整路径
      猜你喜欢
      • 2016-06-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-12-09
      • 1970-01-01
      • 2016-04-17
      • 1970-01-01
      相关资源
      最近更新 更多