Mock.patch in python unittest 可以用于两条路径
Mock.patch in python unittest could work for two paths
我有一个结构如下的目录:
├── 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”中,我使用模拟来模拟“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
然后我 运行 python3.7 -m pytest
在“unittests”目录中,它起作用了。这对我来说很有意义,因为 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 中的模拟时,您经常会遇到短语“在使用的地方模拟它”,如果您是该主题的新手,这并不是很有帮助(但是 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
.
我有一个结构如下的目录:
├── 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”中,我使用模拟来模拟“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
然后我 运行 python3.7 -m pytest
在“unittests”目录中,它起作用了。这对我来说很有意义,因为 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 中的模拟时,您经常会遇到短语“在使用的地方模拟它”,如果您是该主题的新手,这并不是很有帮助(但是 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
.