使用mock的side_effect时为何出现StopIteration错误?
问题:Mock Path时触发StopIteration错误
我编写了一个使用Path的函数,尝试通过mock的side_effect为两次Path调用分配不同返回值,但运行测试时报错StopIteration。
被测试函数代码:
def some_function(input_file, file): compressed_file = Path(input_file) non_compressed_file = Path(file)
测试代码:
@mock.patch('exchanges.impl.bmex.preprocessing.Path') def test_choose_MFII_files(mock_Path): mock_Path.side_effect = [Path(pd.jobserve_config[BMLL_SECTION][WORK_DIR]+ '/MDPRECVOLTICK_MC_20230703.ZIP'), Path(pd.jobserve_config[BMLL_SECTION][WORK_DIR] + '/MERGED_MDPRECVOLTICK_MC_20230703.ZIP')]
报错信息:
_mock_self = <MagicMock name='Path' id='140495179866752'>, args = (PosixPath('/tmp'), 'MERGED_MDPRECVOLTICK_MC_20230703.ZIP'), kwargs = {} self = <MagicMock name='Path' id='140495179866752'>, effect = <list_iterator object at 0x7fc7954ae220> def _execute_mock_call(_mock_self, *args, **kwargs): self = _mock_self # separate from _increment_mock_call so that awaited functions are # executed separately from their call, also AsyncMock overrides this method effect = self.side_effect if effect is not None: if _is_exception(effect): raise effect elif not _callable(effect): > result = next(effect) E StopIteration ../../anaconda3/envs/jobserveee/lib/python3.8/site-packages/mock/mock.py:1163: StopIteration
错误原因:
- 调用次数超出预设列表长度:你给
side_effect传了2个元素的列表,但实际测试中Path被调用的次数超过了2次,列表元素耗尽后迭代器抛出StopIteration。 - 真实Path构造触发额外调用:你在
side_effect里直接使用了真实的Path()构造函数,而这个操作会触发对被mock的Path的调用(因为你mock的是exchanges.impl.bmex.preprocessing.Path,测试代码中创建真实Path时会调用这个被mock的对象),导致额外增加了调用次数,超出了你预设的2次。
解决办法:
不要在side_effect里使用真实的Path实例,改用模拟对象替代:
@mock.patch('exchanges.impl.bmex.preprocessing.Path') def test_choose_MFII_files(mock_Path): # 创建两个模拟的Path实例 mock_compressed = mock.Mock() mock_non_compressed = mock.Mock() # 模拟Path的字符串表示(如果函数中用到的话) mock_compressed.__str__.return_value = f"{pd.jobserve_config[BMLL_SECTION][WORK_DIR]}/MDPRECVOLTICK_MC_20230703.ZIP" mock_non_compressed.__str__.return_value = f"{pd.jobserve_config[BMLL_SECTION][WORK_DIR]}/MERGED_MDPRECVOLTICK_MC_20230703.ZIP" # 设置side_effect为模拟实例列表 mock_Path.side_effect = [mock_compressed, mock_non_compressed] # 调用被测试函数 some_function("test_input", "test_file") # 验证调用次数符合预期 assert mock_Path.call_count == 2
内容的提问来源于stack exchange,提问作者ifrj
相关产品推荐
相关产品推荐

