gpt4 book ai didi

python - 如何模拟在构造函数中实例化的对象?

转载 作者:行者123 更新时间:2023-12-04 16:45:25 25 4
gpt4 key购买 nike

我正在用 Pytest 编写单元测试。我想对一个具有 __init__ 的类进行单元测试方法连接到数据库的对象:

数据模型.py

from my_pkg.data_base_wrapper import DataBaseWrapper

class DataModel:
def __init__(self):
self.db = DataBaseWrapper()
self.db.update_data()

def foo(self):
data = self.db.get_some_data()
# make some processing and return a result

data_base_wrapper.py
class DataBaseWrapper:
def __init__(self):
# Init process of the wrapper
pass

def update_data(self):
# Connect to the database and perform some operations
pass

我试过使用 monkeypatchDataBaseWrapper DataModel 的对象:
from my_pkg.data_model import DataModel

class MockDataBaseWrapper:
@staticmethod
def update_cache():
pass

@staticmethod
def get_table(table):
# Return some data for testing
pass

@pytest.fixture
def data_model(monkeypatch):
monkeypatch.setattr(DataModel, 'db', MockDataBaseWrapper)
data_model = DataModel()

return data_model

但是,我收到以下错误:
monkeypatch = <_pytest.monkeypatch.MonkeyPatch object at 0x7f10221669e8>

@pytest.fixture
def data_model(monkeypatch):
> monkeypatch.setattr(DataModel, 'db', MockDataBaseWrapper)
E AttributeError: <class 'dashboard.datamodel.DataModel'> has no attribute 'db'

我读过类似问题的答案,我可以尝试编写我的 DataBaseWrapper 的子类。并在 DataModel 上更改它类,但我处于相同的情况,因为我不能 monkeypatch __init__的属性方法。但是,如果它不在 __init__ 中,我可以方法。

如何为这种类组合编写测试?也欢迎就如何重写这些类或不同的模式提出建议。

最佳答案

问题是你的 MockDataBaseWrapperDataBaseWrapper完全无关用于 DataModel .

我的建议是摆脱你的MockDataBaseWrapper和:

  • 如果你想保持你当前的结构,你可以使用 patch mock DataBaseWrapper实际上是在 data_model.py 中导入的。
  • from mock import patch
    from my_pkg.data_model import DataModel

    def test_data_model():
    with patch("my_pkg.data_model.DataBaseWrapper") as MockedDB:
    mocked_db = MockedDB()
    data_model = DataModel()
    assert data_model.db is mocked_db
    patch上下文管理器将替换 DataBaseWrapper使用 Mock 实例在 data_model.py 中导入的类,并让您与该模拟进行交互,这允许我在这里验证它是否已实例化。

    Note that it is very important to patch the class in the module where it is imported (and not in the model where it is defined, i.e we patch your_package.data_model.DataBaseWrapper and not your_package.data_base_wrapper.DataBaseWrapper)


  • 如果你不介意改变你的类,那么通常的模式是注入(inject) db参数进入 DataModel 的构造函数. mock 它然后成为小菜一碟。
  • class DataModel:
    def __init__(self, db):
    self.db = db
    self.db.update_data()

    from mock import patch, Mock
    from my_pkg.data_model import DataModel

    def test_data_model():
    mocked_db = Mock()
    data_model = DataModel(mocked_db)
    assert data_model.db is mocked_db

    关于python - 如何模拟在构造函数中实例化的对象?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57859599/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com