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

如何Mock Python Thread子类run方法中调用的函数及替代测试方案

正确Mock的解决方案

问题根源

你当前的patch目标错误:MyThread类里并没有my_function属性,run方法调用的是导入到my_thread模块中的my_function引用,不是my_function模块里的原函数,也不是MyThread类的成员。之前patchMyThread.my_function完全无效,patchmy_function.my_function也不生效,因为my_thread模块已经缓存了原函数的引用。

修正后的测试代码

修改patch的目标为my_thread.my_function,同时简化测试逻辑(直接调用run是在当前线程执行,无需多余的sleep和join操作):

from my_thread import MyThread
import unittest
from unittest.mock import patch


def mock_my_function():
    print("not doing something")
    return False


class TestMyThread(unittest.TestCase):

    def setUp(self):
        self.my_thread = MyThread()

    def test_my_thread_run_method(self):
        # 关键:patch的是my_thread模块中导入的my_function引用
        with patch("my_thread.my_function", side_effect=mock_my_function) as mock_func:
            # 手动设置事件,避免循环直接退出
            self.my_thread.running.set()
            # 执行run方法
            self.my_thread.run()
            # 立即清除事件终止循环
            self.my_thread.running.clear()
            
            # 断言mock函数被调用一次
            mock_func.assert_called_once()
            # 验证返回值符合预期
            self.assertEqual(mock_func.return_value, False)

线程启动场景的测试调整

如果是通过self.my_thread.start()启动新线程,测试逻辑需要稍作调整:

def test_my_thread_start(self):
    with patch("my_thread.my_function", side_effect=mock_my_function) as mock_func:
        self.my_thread.start()
        # 等待足够让一次循环执行的时间(无需等满3秒)
        import time
        time.sleep(0.5)
        self.my_thread.running.clear()
        self.my_thread.join()
        
        mock_func.assert_called_once()
不使用Mock的替代测试方案

通过依赖注入重构MyThread,让它支持传入自定义函数,测试时直接传入测试用函数即可:

重构后的MyThread代码(my_thread.py)

from my_function import my_function
from threading import Thread, Event
import time


class MyThread(Thread):

    def __init__(self, target_func=None):
        super().__init__(name="MyThread")
        self.running = Event()
        # 允许注入自定义函数,默认使用原my_function
        self.target_func = target_func or my_function

    def run(self):
        self.running.set()

        while self.running.is_set():
            return_value = self.target_func()
            print(return_value)
            time.sleep(3)

对应的测试代码

from my_thread import MyThread
import unittest


class TestMyThread(unittest.TestCase):

    def test_my_thread_with_injected_func(self):
        # 用计数器跟踪函数调用次数
        call_count = 0
        def test_func():
            nonlocal call_count
            call_count += 1
            return False
        
        my_thread = MyThread(target_func=test_func)
        my_thread.running.set()
        my_thread.run()
        my_thread.running.clear()
        
        # 断言函数被调用一次
        self.assertEqual(call_count, 1)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 05:06:19