[英]How can I use pytest monkeypatch to mock calls to SQLAlchemy create_engine call
I have a function that returns an SQLAlchemy engine object我有一个返回 SQLAlchemy 引擎对象的函数
create_db.py: create_db.py:
from sqlalchemy import create_engine
def init_db():
return create_engine("sqlite://", echo=True, future=True)
and I've a test that's attempting to use pytest's monkeypatch to mock the call to create_engine.我有一个测试试图使用pytest的monkeypatch来模拟对create_engine的调用。
test_db.py: test_db.py:
import sqlalchemy
from create_db import init_db
def test_correct_db_path_selected(monkeypatch):
def mocked_create_engine():
return "test_connection_string"
monkeypatch.setattr(sqlalchemy, "create_engine", mocked_create_engine())
engine = init_db()
assert engine == "test_connection_string"
When I run pytest, the test is failing as a real sqlalchemy engine object is getting returned, not the mocked string.当我运行 pytest 时,测试失败,因为返回的是真正的 sqlalchemy 引擎对象,而不是模拟的字符串。
AssertionError: assert Engine(sqlite://) == 'test_connection_string'
I've tried the following calls to setattr but they all fail in the same manner:我尝试了以下对 setattr 的调用,但它们都以相同的方式失败:
monkeypatch.setattr("sqlalchemy.engine.create.create_engine", mocked_create_engine)
monkeypatch.setattr(sqlalchemy.engine.create, "create_engine", mocked_create_engine)
monkeypatch.setattr(sqlalchemy.engine, "create_engine", mocked_create_engine)
I've gotten the basic examples from pytest docs to work but it doesn't cover a static function from a library.我已经从 pytest 文档中获得了基本示例,但它没有涵盖库中的静态函数。 Does anyone have any suggestions on what I'm doing wrong?
有人对我做错了什么有任何建议吗?
So I've found a solution for my problem, but I'm still not clear on why the above code doesn't work.所以我找到了解决我的问题的方法,但我仍然不清楚为什么上面的代码不起作用。
If I change my create_db.py to directly call sqlalchemy.create_engine, the mocking function works.如果我将我的 create_db.py 更改为直接调用 sqlalchemy.create_engine,则模拟函数将起作用。
create_db.py: create_db.py:
import sqlalchemy
def init_db():
return sqlalchemy.create_engine("sqlite://")
test_db.py: test_db.py:
import sqlalchemy
from create_db import init_db
class MockEngine:
def __init__(self, path):
self.path = path
def test_correct_db_path_selected(monkeypatch):
def mocked_create_engine(path):
return MockEngine(path=path)
monkeypatch.setattr(sqlalchemy, "create_engine", mocked_create_engine)
engine = init_db()
assert engine.path == "sqlite://"
I don't mind changing my code to make it more testable but I'd still like to know if it's possible to mock a call to the original create_engine call.我不介意更改我的代码以使其更具可测试性,但我仍然想知道是否可以模拟对原始 create_engine 调用的调用。 I'll leave the question and answer up in case any else runs into the same problem.
我会留下问题并回答,以防其他人遇到同样的问题。
Edit: I found a solution that doesn't involve changing the code to be tested.编辑:我找到了一个不涉及更改要测试的代码的解决方案。 The following call to setattr will mock a function call that isn't on an object:
以下对 setattr 的调用将模拟不在对象上的函数调用:
monkeypatch.setattr(create_db, "create_engine", mocked_create_engine)
This works as it's telling monkeypatch to mock direct calls to create_engine in the create_db.py file.这有效,因为它告诉 monkeypatch 在 create_db.py 文件中模拟对 create_engine 的直接调用。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.