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

如何用unittest patch装饰器修补threading.Lock方法?

解决pytest修补Lock.acquire/release时的AttributeError问题

错误原因

你遇到的报错是因为Lock是类,acquire和release是Lock实例的方法,而非Lock类本身的属性。直接通过@patch("my_project.main.Lock.acquire")尝试在类层面修补实例方法,会因为类上不存在该属性而触发AttributeError。而Thread.start是Thread类的方法,所以类层面的修补可以正常生效。

正确的测试写法

方法一:修补整个Lock类,验证实例方法调用

通过修补my_project.main.Lock类,让它返回一个Mock实例,以此验证acquire和release的调用逻辑:

from unittest.mock import patch, MagicMock
import my_project.main

def test_lock_usage():
    with patch("my_project.main.Lock") as mock_lock_cls:
        # 构造Mock锁实例
        mock_lock = MagicMock()
        mock_lock_cls.return_value = mock_lock
        
        # 初始化线程并执行run方法
        thread = my_project.main.MyThread()
        thread.run()
        
        # 验证锁的acquire和release被正确调用
        mock_lock.acquire.assert_called_once()
        mock_lock.release.assert_called_once()

方法二:直接修补线程实例的锁方法

如果需要自定义锁方法的行为,可以针对已创建的线程实例的lock属性进行修补:

from unittest.mock import patch
import my_project.main

def test_custom_lock_behavior():
    # 创建线程实例
    thread = my_project.main.MyThread()
    
    # 修补该实例锁的acquire和release方法
    with patch.object(thread.lock, "acquire") as mock_acquire, \
         patch.object(thread.lock, "release") as mock_release:
        # 自定义acquire的返回值
        mock_acquire.return_value = True
        
        thread.run()
        
        # 验证方法调用
        mock_acquire.assert_called_once()
        mock_release.assert_called_once()

额外注意

  • 原测试函数的装饰器使用有误:@patch需要将生成的Mock对象作为参数传递给测试函数,比如原patch_thread_start函数应改为:
    @patch("my_project.main.Thread.start")
    def test_patch_thread_start(mock_start):
        print("patching start ")
    
  • with语句操作锁时,实际会调用锁的__enter__(内部触发acquire)和__exit__(内部触发release),所以验证acquire/release的调用即可覆盖with锁的逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 20:23:22