如何用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
相关产品推荐
相关产品推荐

