Pytest类级patch残留影响其他测试类问题求助
问题原因
- Python模块缓存机制:Python会将已导入的模块存入
sys.modules缓存,后续导入直接复用缓存对象。如果第二个测试文件的模块级导入发生在第一个测试的补丁生效期间,会将mock版本的SnowFlakeConnector缓存到自身命名空间,即便补丁后续被清理,该引用也不会自动更新。 - pytest执行顺序与导入时机:pytest默认按文件名排序执行测试,
kernel_application_test.py先于sql_loader_test.py运行。若后者的模块级导入在前者补丁生效阶段完成,就会导致测试拿到mock对象。 - unittest补丁的局限性:类级补丁仅会在测试类所有方法执行完毕后恢复模块属性,但如果第二个测试已在补丁生效时获取了
SnowFlakeConnector的引用,清理操作无法更新已导入到测试文件中的旧引用。
解决办法
延迟导入到测试方法内:将
sql_loader_test.py的模块级导入移至测试方法内部,确保每次执行测试时都从模块获取最新的SnowFlakeConnector(此时补丁已清理):# /test/sql_loader_test.py import unittest class TestSqlLoader(unittest.TestCase): def test_something(self): from customlib.snowflake import SnowFlakeConnector # 测试逻辑用pytest fixture管理补丁:改用pytest的fixture封装补丁,限定作用域为类或函数,自动处理补丁的创建与清理,避免跨文件污染:
# /test/kernel_application_test.py import pytest from unittest import mock @pytest.mark.usefixtures("snowflake_mock") class TestExecuteApplication: @pytest.fixture(scope="class") def snowflake_mock(self): with mock.patch('customlib.snowflake.SnowFlakeConnector', autospec=True) as mock_conn: yield mock_conn手动重置模块缓存:若必须保留模块级导入,可在第二个测试类的初始化方法中手动清理并重新加载模块:
# /test/sql_loader_test.py import unittest import sys class TestSqlLoader(unittest.TestCase): @classmethod def setUpClass(cls): if 'customlib.snowflake' in sys.modules: del sys.modules['customlib.snowflake'] global snowflake import customlib.snowflake as snowflake def test_something(self): # 使用snowflake.SnowFlakeConnector(已恢复为原始类) pass
内容的提问来源于stack exchange,提问作者gontxomde
相关产品推荐
相关产品推荐

