You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

测试中mock pathlib.Path.is_dir()失效的问题排查求助

问题分析与解决方案

我来帮你拆解下问题出在哪,以及怎么修复这个mock失效的问题:

核心问题:mock错了对象

你业务代码里调用的是Path实例的is_dir()方法,但你的测试代码却mock了Path类本身的is_dir属性,两者完全不是一回事:

  • 业务代码逻辑:path = Path(element) → 创建Path类的实例 → 调用path.is_dir()(实例方法)
  • 你的测试操作:给source_code.Path.is_dir赋值了一个MagicMock → 这是给类加了个静态属性,实例调用is_dir()时根本不会用到它

所以你的side_effect完全没生效,调用path.is_dir()得到的是实例默认的mock对象(在Python里mock对象本身是truthy的,所以你的if result判断永远为True)。

另外提一句:你业务代码里还有个小bug,print(f"#MBB SC: {dir} -> {result}")里的dir是Python内置函数,不是你想输出的路径,应该改成element或者path。

正确的测试实现

我们需要让Path类创建的每一个实例,其is_dir()方法按顺序返回True和False。这里推荐用unittest.mock.patch来更优雅地实现:

方案一:逐个定义mock实例

import pytest
from unittest.mock import call, patch, MagicMock
import source_code

class TestSourceCode():
    @patch('source_code.Path')
    def test_simple_method(self, mock_path_class):
        # 创建两个mock实例,分别设置is_dir的返回值
        mock_tmp_instance = MagicMock()
        mock_tmp_instance.is_dir.return_value = True
        
        mock_test_instance = MagicMock()
        mock_test_instance.is_dir.return_value = False

        # 让Path类按顺序返回这两个实例
        mock_path_class.side_effect = [mock_tmp_instance, mock_test_instance]

        # 调用业务方法
        source_code.simple_method()

        # 验证Path类的调用是否符合预期
        assert mock_path_class.call_args_list == [call('/tmp'), call('/tmp/test')]
        
        # 验证每个实例的is_dir方法都被调用了一次
        mock_tmp_instance.is_dir.assert_called_once()
        mock_test_instance.is_dir.assert_called_once()

方案二:用动态函数简化写法

如果不想单独创建每个实例,也可以用一个动态函数来控制返回值:

import pytest
from unittest.mock import call, patch
import source_code

class TestSourceCode():
    @patch('source_code.Path')
    def test_simple_method(self, mock_path_class):
        # 定义is_dir的返回序列
        is_dir_results = [True, False]
        
        def mock_is_dir():
            return is_dir_results.pop(0)
        
        # 让所有Path实例的is_dir方法调用这个动态函数
        mock_path_instance = mock_path_class.return_value
        mock_path_instance.is_dir.side_effect = mock_is_dir

        source_code.simple_method()

        # 验证调用次数和参数
        assert mock_path_class.call_args_list == [call('/tmp'), call('/tmp/test')]
        assert mock_path_instance.is_dir.call_count == 2

为什么原来的测试看不到is_dir的调用?

因为你mock的source_code.Path.is_dir是类属性,但业务代码里从来没有调用过Path.is_dir()(类方法),所有调用都是针对实例的is_dir(),所以这个mock的调用计数永远是0,自然看不到调用记录。

内容的提问来源于stack exchange,提问作者MarcnB

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.29 11:39:10