Python测试疑问:pytest mocker Fixture自动注入原理及迁移至unittest.TestCase的方法与困惑
Python测试疑问:pytest mocker Fixture自动注入原理及迁移至unittest.TestCase的方法与困惑
一、pytest mocker Fixture自动注入的原理
你提到的“mocker对象自动传到mock_dataiku函数”并不是什么黑魔法,这是pytest的fixture依赖注入机制在起作用:
mocker是pytest-mock插件提供的内置fixture,pytest会自动识别测试函数或其他fixture中名为mocker的参数。- 当你定义
mock_dataiku(mocker)这个fixture时,pytest会解析到它依赖mocker,于是先实例化mocker对象,再把它作为参数传递给mock_dataiku函数,最终生成你需要的mock_project对象。 - 当运行
test_cleanse_existing_variable(mock_dataiku)时,pytest又会解析到这个测试函数依赖mock_dataikufixture,于是重复上述流程,把生成好的mock_project传入测试函数。
简单说就是:pytest会自动追踪所有fixture之间的依赖关系,按顺序创建并注入对应的对象,不需要你手动传递。
二、迁移至unittest.TestCase的方法与相关困惑
为什么fixture在unittest.TestCase里不生效?
unittest是Python标准库的测试框架,它有自己的一套执行逻辑(依赖setUp/tearDown方法),和pytest的fixture系统是不兼容的。因为unittest的测试方法只能接收self作为参数,pytest无法把fixture对象注入进去,所以你直接在unittest类里用pytest的mocker肯定会报错。
要不要用unittest.TestCase?
这取决于你的项目场景:
- 如果你的项目已经大量使用unittest,或者需要兼容标准库的测试运行方式,那可以继续用;
- 如果是新项目,更推荐直接用pytest的函数式/类式测试(不用继承unittest.TestCase),因为pytest的fixture比unittest的
setUp/tearDown灵活太多,还能兼容unittest的测试用例。
如果一定要用unittest.TestCase,怎么改写测试?
你需要用Python标准库的unittest.mock模块来替代pytest-mock的mocker,手动在setUp方法里完成mock操作:
import unittest from unittest.mock import MagicMock, patch from your_module import cleanse # 替换成你的实际模块名 class TestCleanse(unittest.TestCase): def setUp(self): # 手动mock dataiku.api_client self.mock_client = MagicMock() self.mock_project = MagicMock() # 使用patch装饰器或者上下文管理器,这里用start/stop来控制生命周期 self.patch_api_client = patch('dataiku.api_client', return_value=self.mock_client) self.patch_api_client.start() self.mock_client.get_project.return_value = self.mock_project def tearDown(self): # 清理mock self.patch_api_client.stop() def test_cleanse_existing_variable(self): # 设置返回值 self.mock_project.get_variables.return_value = { "local": {"var1": "old_value", "comment": "some_comment"} } # 执行测试 cleanse(["var1", "comment"]) # 断言 expected_variables = {"local": {"var1": "-1", "comment": ""} } self.mock_project.set_variables.assert_called_with(expected_variables)
可以直接省略类用pytest吗?
当然可以!而且这是pytest最推荐的写法之一,你原来的函数式测试写法完全没问题,fixture的使用也更顺畅。如果不需要兼容unittest的特定需求,完全可以保持原来的结构,不用强行改成unittest.TestCase的形式。
备注:内容来源于stack exchange,提问作者Daniel Ďurkovič
相关产品推荐
相关产品推荐

