【问题标题】:Use mock to patch sleep in unit test在单元测试中使用 mock 修补睡眠
【发布时间】:2026-01-28 23:05:01
【问题描述】:

我有一段代码位于这样的模块中:

MyWorker.py:

from gevent import sleep

class MyWorker(object):
  def run(self):
    for _ in range(10):
      do_something()
      sleep(1)

然后我想在模拟睡眠时测试这个。我尝试了多种方法,但都失败了。我认为应该可行的一种方法:

from mock import patch
from x.y.z.MyWorker import MyWorker

class TestWorker(unitest.testCase):
  def Test_my_worker(self):
    with patch('x.y.z.MyWorker.sleep'):
      a = MyWorker()
      a.run()

【问题讨论】:

  • 您可以尝试将from x.y.z... 行移到with patch... 之后吗?
  • 看起来这段代码可以工作......你确定这相当于不适合你的代码吗?
  • @rodrigo 你的把戏奏效了。但是我应该如何为每个单元测试做呢?然后问题是我应该如何修补在该模块中导入但在单元测试中没有导入的睡眠功能?

标签: python unit-testing mocking


【解决方案1】:

我尝试了更多,结果发现它很容易修复: 将from x.y.z.MyWorker import MyWorker 更改为from x.y.z.MyWorker import MyWorker, sleep,或者您可以更改from x.y.z.MyWorker import * 并且所有单元测试都可以工作。上面的评论给了我这个想法。

这就是我最终要做的:

from x.y.z.MyWorker import MyWorker, sleep

Class TestMyWorker(unittest.TestCase):

  def setUp(self):
    self.patcher = patch('x.y.z.MyWorker.sleep')
    self.patcher.start()

  def tearDown(self):
    self.patcher.stop()

  def Test_my_worker_success():
    MyWorker().run()

  def Test_my_worker_fail():
    ...

【讨论】:

  • 那个答案没有意义:如果它有效,那么问题中的代码也应该有效。
  • 如果import sleep 让它工作,你应该在MyWorker.py 中进行某种惰性初始化
【解决方案2】:

这是模拟睡眠的完整工作版本

# TestMyWorker.py
#!/usr/bin/python
import unittest
import mock

# myWorker.py MyWorker(class)
from myWorker import MyWorker

class TestWorker(unittest.TestCase):

    # myWorker.py - mock away sleep
    @mock.patch('myWorker.sleep')
    def test_my_worker(self, mock_sleep):
        # mock away the sleep()
        mock_sleep.return_value = False
        worker = MyWorker()
        # should run witout calling sleep()
        worker.run()
        self.assertFalse(mock_sleep.sleep.called,"Fail - sleep really called!")

if __name__ == '__main__':
    suite = unittest.TestLoader().loadTestsFromTestCase(TestWorker)
    unittest.TextTestRunner(verbosity=2).run(suite)

【讨论】: