【问题标题】:Mock.patch in python unittest could work for two pathspython unittest 中的 Mock.patch 可以用于两条路径
【发布时间】:2020-06-23 02:06:44
【问题描述】:

我有一个具有这种结构的目录:

├── aaa.py
├── src
│   └── subsrc
│       ├── else.py
│       └── util.py  (there is a "foo" function")
└── tests
    ├── __init__.py
    └── unittests
        ├── __init__.py
        └── test_aaa.py

所以“aaa.py”、“tests”目录和“src”目录都在项目根目录中。在“test_aaa.py”中,我使用mock来模拟“util.py”中的函数:

from src.subsrc.util import foo
import pytest
from unittest import mock

@mock.patch("src.subsrc.util.foo")
def test_foo(mock):
    mock.return_value = 111

然后我在“unittests”目录中运行python3.7 -m pytest,它起作用了。这对我来说很有意义,因为 pytest 会找到第一个没有 __init__.py 的目录,然后将其添加到 PATH(在这种情况下,将添加项目根目录)以便它可以找到“src.subsrc.util.foo”。

但后来我对“test_aaa.py”做了一个小改动,在它的“mock.patch”中,我在开头添加了“aaa”:

from src.subsrc.util import foo
import pytest
from unittest import mock

@mock.patch("aaa.src.subsrc.util.foo")
def test_foo(mock):
    mock.return_value = 111

它仍然有效,“aaa.py”是一个可执行文件,在“aaa.py”中:

#!python3.7
from src.subsrc.else import other

if __name__ = "__main__":
   # ...
   pass

我很困惑为什么@mock.patch("aaa.src.subsrc.util.foo") 也有效,Python 是否如此聪明以至于它可以忽略“aaa”然后去“src.subsrc..”去寻找它需要的东西?谢谢!

更新: 我怀疑是不是因为“aaa.py”的名字很特别,所以我把它改成了不同的名字,但它仍然有效。就像我将其更改为“bbb.py”,然后在 mock.patch 中,“aaa.src ...”不起作用但“bbb.src ...”仍然有效。所以我确信“mock.patch”会首先找到这个可执行文件。

更新: 我猜这可能与“mock.patch()”的工作原理有关?

【问题讨论】:

    标签: python mocking pytest python-3.7 python-unittest


    【解决方案1】:

    您的示例似乎有点过于精简,但我会尝试扩展它以进行解释。在阅读 Python 中的 mock 时,您经常会遇到“mock it where it's used”这样的短语,如果您是该主题的新手(但here's an excellent article on this concept),这并不是很有帮助。

    在您的test_aaa.py 中,您可能想要测试您的aaa.py 模块的某些功能,该模块可能会从src/subsrc/util.py 调用某些功能。在aaa.py 模块中导入foo() 函数后,您应该将@mock.patch 指向@mock.patch("aaa.foo") 的确切位置。通过这样做,您的模拟将可以访问您将要测试的函数中的所有foo() 调用,即aaa.do_something()。我将您的示例扩展如下:

    # aaa.py
    
    from src.subsrc.util import foo
    
    def do_something():
        return foo()
    
    if __name__ == "__main__":
        value = do_something()
        print(f"value is {value}")
    
    # src/subsrc/util.py
    
    def foo():
        return 222
    
    # tests/unittests/test_aaa.py
    
    from unittest import mock
    from aaa import do_something
    
    @mock.patch("aaa.foo")
    def test_foo(foo_mocked):
        foo_mocked.return_value = 111
        value = do_something()
        assert value == 111
    

    当像python aaa.py 一样执行此操作时,我得到了预期的输出 (value is 222),而测试通过它的 assert value == 111

    在您的示例中,@mock.patch("src.subsrc.util.foo") 显然有效,但可能没有达到您的预期。从您的示例代码中,我看不出@mock.patch("aaa.src.subsrc.util.foo") 不应该返回ModuleNotFoundError

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-02-05
      • 1970-01-01
      • 1970-01-01
      • 2022-01-22
      相关资源
      最近更新 更多