为何测试用例结束后线程内调用的方法Mock未生效?
问题:多线程场景下Mock方法仅在sleep时生效的原因
代码文件
one.py
class One: def __init__(self) -> None: pass def startS(self): self._doS() def _doS(self): print("Inside doS method") if not self.open(): print("The patch didn't work") return False print("The patch worked well") return True def open(self): print("Inside open method") return False
two.py
from one import One from threading import Thread class Two(One): def __init__(self) -> None: super().__init__() def startS(self): self.sThread = Thread(target=super().startS) self.sThread.daemon = True self.sThread.start()
测试代码(test_two.py)
import unittest from unittest import mock from time import sleep from two import Two @mock.patch('two.One.open', mock.Mock(return_value=True)) class TestDummy(unittest.TestCase): def test_first(self) -> None: self.two = Two() self.two.startS() #sleep(1) if __name__ == '__main__': unittest.main()
运行结果
无sleep时的输出
Inside doS method .Inside open method The patch didn't work Ran 1 test in 0.001s OK
有sleep时的输出
Inside doS method The patch worked well . Ran 1 test in 1.002s OK
原因解析
核心问题是守护线程的执行时序与测试上下文的生命周期不匹配:
@mock.patch的生效范围仅限于测试方法test_first的执行过程,一旦测试方法执行完毕,Mock会被立即撤销。- 调用
self.two.startS()后,守护线程是异步启动的,但测试方法会立刻执行结束,此时Mock已经失效。而守护线程可能在Mock撤销后才开始调用open(),这时调用的是原类的open()方法(返回False),所以出现未生效的结果。 - 加入
sleep(1)后,测试方法会等待一段时间,让守护线程有足够时间在Mock生效期间完成open()调用,因此Mock能正常工作。
解决方法
不要依赖sleep这种不可靠的等待方式,应该主动等待线程执行完成:
修改测试方法,启动线程后调用join()等待线程结束:
def test_first(self) -> None: self.two = Two() self.two.startS() self.two.sThread.join() # 等待线程执行完成
这样能确保线程在Mock生效的上下文内完成所有调用,无需sleep也能得到正确结果。
内容的提问来源于stack exchange,提问作者tatti
相关产品推荐
相关产品推荐

