运行时替换其他类方法中的路径方案咨询
问题描述
我有两个分属不同模块的类,一个负责实际功能,一个负责测试功能:
# ModuleA class ModuleA: def __init__(self, path): self.import_path = None def import_data(self): # 这里硬编码了路径来源,导致测试时无法覆盖 self.import_path = sales.__path__["data"] self.input = pd.read_excel( self.import_path, index_col=False, engine="openpyxl", dtype=object, ) return self.input # ModuleB class ModuleB: def __init__(self, path): self.import_test_path = None def test_import_data(self): self.import_test_path = self.__path__["data"] # 尝试替换路径,但因为ModuleA的方法内部会重新赋值,所以无效 ModuleA.import_path = self.import_test_path ModuleA.import_data()
问题是:我在ModuleB里定义了测试路径,但调用方法后无法覆盖ModuleA实例的import_path——因为这个路径是在import_data方法内部直接赋值的。请问能否通过Monkeypatching等方式替换该路径?
解决方案
方法1:Monkeypatch sales模块的__path__
既然ModuleA.import_data直接从sales.__path__["data"]获取路径,你可以直接Monkeypatch这个sales模块的__path__字典,让它返回测试路径:
# 修改ModuleB的test_import_data方法 def test_import_data(self): self.import_test_path = self.__path__["data"] # 保存原始路径,测试后恢复(避免影响其他用例) original_data_path = sales.__path__["data"] sales.__path__["data"] = self.import_test_path try: # 实例化ModuleA并执行方法 module_a = ModuleA(...) module_a.import_data() # 这里添加你的测试断言逻辑 finally: # 恢复原始路径 sales.__path__["data"] = original_data_path
方法2:Monkeypatch pd.read_excel
如果不想改动sales模块的路径,可以直接拦截pd.read_excel的调用,强制它读取测试文件:
def test_import_data(self): self.import_test_path = self.__path__["data"] # 定义替代的read_excel函数 def mock_read_excel(path, **kwargs): # 忽略传入的原始路径,直接读取测试文件 return pd.read_excel(self.import_test_path, **kwargs) # 替换原函数 original_read = pd.read_excel pd.read_excel = mock_read_excel try: module_a = ModuleA(...) result = module_a.import_data() # 测试断言 finally: # 恢复原函数 pd.read_excel = original_read
方法3:重构ModuleA,让路径可配置(推荐)
硬编码路径会导致可测试性差,长远来看建议重构ModuleA,让路径支持外部传入:
# 重构后的ModuleA class ModuleA: def __init__(self, path, data_path=None): self.path = path # 允许初始化时传入自定义路径,没有的话用默认值 self.import_path = data_path def import_data(self): if not self.import_path: self.import_path = sales.__path__["data"] self.input = pd.read_excel( self.import_path, index_col=False, engine="openpyxl", dtype=object, ) return self.input # 测试时直接传入测试路径 class ModuleB: def __init__(self, path): self.import_test_path = self.__path__["data"] def test_import_data(self): # 实例化时直接指定测试路径,无需Monkeypatch module_a = ModuleA(..., data_path=self.import_test_path) result = module_a.import_data() # 测试断言
这种方式不需要任何Monkeypatch就能轻松替换路径,代码的灵活性和可维护性也更好。
内容的提问来源于stack exchange,提问作者29nivek
相关产品推荐
相关产品推荐

