我正在用Pytest编写单元测试。我想对在其__init__
方法上具有连接到数据库的对象的类进行单元测试:
data_model.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
我尝试在monkeypatch
的{{1}}对象上使用DataBaseWrapper
:
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
方法中,我可以。
如何为此类课程编写测试?也欢迎提出有关如何重写这些类或其他模式的建议。
答案 0 :(得分:1)
问题在于您的MockDataBaseWrapper
与DataBaseWrapper
中使用的DataModel
完全无关。
我的建议是摆脱您的MockDataBaseWrapper
和:
patch
来模拟实际导入到data_model.py中的DataBaseWrapper
。 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
上下文管理器将使用Mock实例替换在data_model.py中导入的DataBaseWrapper
类,并让您与该模拟进行交互,这使我在此处可以验证它是否已实例化
请注意,在导入类的模块中修补该类非常重要(而不是在定义该类的模型中进行修补,即,我们修补
your_package.data_model.DataBaseWrapper
而不是your_package.data_base_wrapper.DataBaseWrapper
)
db
参数注入DataModel
的构造函数中。然后嘲笑它就成了小菜一碟。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