Phi*_*ert 13 python mocking pytest python-unittest
给定这样的文件夹结构:
dags/
**/
code.py
tests/
dags/
**/
test_code.py
conftest.py
Run Code Online (Sandbox Code Playgroud)
其中 dags 作为 src 文件的根,“dags/a/b/c.py”导入为“abc”。
我想在code.py中测试以下函数:
dags/
**/
code.py
tests/
dags/
**/
test_code.py
conftest.py
Run Code Online (Sandbox Code Playgroud)
但我面临的问题是我无法找到修补get_connfrom的方法dag_common.connections。我尝试了以下操作:
import os
import sys
# adds dags to sys.path for tests/*.py files to be able to import them
sys.path.append(os.path.join(os.path.dirname(__file__), "..", "dags"))
{{fixtures}}
Run Code Online (Sandbox Code Playgroud)
我测试了以下替代品{{fixtures}}:
(1.a) - 默认
from dag_common.connections import get_conn
from utils.database import dbtypes
def select_records(
conn_id: str,
sql: str,
bindings,
):
conn: dbtypes.Connection = get_conn(conn_id)
with conn.cursor() as cursor:
cursor.execute(
sql, bindings
)
records = cursor.fetchall()
return records
Run Code Online (Sandbox Code Playgroud)
(1.b) - 用 dags 作为路径前缀
import os
import sys
# adds dags to sys.path for tests/*.py files to be able to import them
sys.path.append(os.path.join(os.path.dirname(__file__), "..", "dags"))
{{fixtures}}
Run Code Online (Sandbox Code Playgroud)
(1.c) - 1.a,范围=“会话”
(1.d) - 1.b,范围=“会话”
(1.e) - 对象修补模块本身
@pytest.fixture(autouse=True, scope="function")
def mock_get_conn():
with mock.patch("dag_common.connections.get_conn") as mock_getter:
yield mock_getter
Run Code Online (Sandbox Code Playgroud)
(1.f) - 1.a,但使用 pytest-mock 夹具
@pytest.fixture(autouse=True, scope="function")
def mock_get_conn():
with mock.patch("dags.dag_common.connections.get_conn") as mock_getter:
yield mock_getter
Run Code Online (Sandbox Code Playgroud)
(1.g) - 1.b,但使用 pytest-mock 夹具
(1.h) - 1.a,但使用 pytest 的 Monkeypatch
@pytest.fixture(autouse=True, scope="function")
def mock_get_conn():
import dags.dag_common.connections
mock_getter = mock.MagicMock()
with mock.patch.object(dags.dag_common.connections, 'get_conn', mock_getter):
yield mock_getter
Run Code Online (Sandbox Code Playgroud)
(2.a) - 装饰器@mock.patch(“dag_common.connections.get_conn”)
@pytest.fixture(autouse=True, scope="function")
def mock_get_conn(mocker):
with mocker.patch("dag_common.connections.get_conn") as mock_getter:
yield mock_getter
Run Code Online (Sandbox Code Playgroud)
(2.b) - (2.a) 但带有“dags”。字首
(2.c) - 上下文管理器
@pytest.fixture(autouse=True, scope="function")
def mock_get_conn(mocker, monkeypatch):
import dags.dag_common.connections
mock_getter = mocker.MagicMock()
monkeypatch.setattr(dags.dag_common.connections, 'get_conn', mock_getter)
yield mock_getter
Run Code Online (Sandbox Code Playgroud)
(2.d) - (2.c) 但带有“dags”。字首
但可惜的是,无论我选择什么解决方案,要模拟的函数仍然会被调用。我确保分别尝试每个解决方案,并在尝试之间终止/清除/重新启动我的 pytest-watch 进程。
我觉得这可能与我干预conftest.py中的sys.path有关,因为除此之外我觉得我已经用尽了所有可能性。
知道我该如何解决这个问题吗?
Jar*_*iuk 27
是的。最初当我学习修补和嘲笑时,我也对此进行了斗争,并且知道它是多么令人沮丧,因为你似乎做的一切都是正确的,但它不起作用。我同情你!
这实际上就是嘲笑进口东西的工作原理,一旦你意识到这一点,它实际上是有道理的。
问题在于导入的工作方式是使导入的模块在导入所在的上下文中可用。
让我们假设您的code.py模块位于“my_package”文件夹中。您的代码随后可用my_package.code。一旦您from dag_common.connections import get_conn在code模块中使用 - 导入的内容get_conn就可以作为...使用。my_package.code.get_conn
在这种情况下,您需要修补的my_package.code.get_conn不是您从中导入 get_conn 的原始包。
一旦你意识到这一点,修补就会变得容易得多。
| 归档时间: |
|
| 查看次数: |
23063 次 |
| 最近记录: |