【问题标题】:Mocking datetime.now() midway through a unittest.TestCase in Python 2.7在 Python 2.7 中通过 unittest.TestCase 模拟 datetime.now()
【发布时间】:2019-03-03 14:06:25
【问题描述】:

我正在尝试测试一些去抖动逻辑 - 这些是我使用 2.7 运行时环境为 Google App Engine webapp 运行的本地单元测试。我所有的其他测试都进行得很顺利,但这个让我很难过!

def testThat_emailDebouncingWorks(self):

  # Do something, it triggers an email.
  doSomething()
  self.assertEqual(emails_sent, 1)

  # Do something again, the new email is debounced.
  doSomething()
  self.assertEqual(emails_sent, 1)

  # After an hour, the emails should start working again...
  mockWaitingAnHour()
  doSomething()
  self.assertEqual(emails_sent, 2)

  # ... and so should the debouncing.
  doSomething()
  self.assertEqual(emails_sent, 2)

正在测试的文件使用 datetime.now() 记录电子邮件的发送时间,然后在以后的所有尝试中重新运行 datetime.now(),如果不到一小时则提前返回。

有两个问题:

  1. 我认为 unittest 库仅在 3.X 中添加了模拟支持,我并不热衷于更新我的整个应用程序。

  2. 即使我使用的是 3.X,我看到的所有示例都是关于为整个测试用例伪造日期时间响应(使用测试 def 上方的模拟装饰器)。而我想在测试中途改变这种行为,而不是整个案例。

有什么建议吗?提前致谢!

【问题讨论】:

    标签: python-unittest


    【解决方案1】:

    好的,我已经深入了解并想记录下任何在 Google 上找到此内容的人的答案;)

    1.在 AppEngine for Python 2.7 上启用模拟

    您需要按照说明从the official docs 复制第三方库(在我们的例子中为“mock”)。值得注意的是,在 Ubuntu 上,建议的命令:

    pip install -t lib/ mock
    

    会失败。你会得到这样的错误:

    DistutilsOptionError: can't combine user with prefix, exec_prefix/home, or install_(plat)base
    

    这与与 Ubuntu 的奇怪冲突有关,该冲突似乎多年来一直未修复,您会看到很多人建议使用 virtualenv 解决方法。我添加了 --system 标志:

    pip install --system -t lib/ mock
    

    而且效果很好。请记住按照 appengine_config 的其余说明进行操作,您应该已设置好。 “import mock”是一种很好的检查方式。

    2。模拟 datetime.now() 调用

    我正在测试的模块使用:

    from datetime import datetime
    

    在我的测试模块中,导入一些东西:

    from mock import patch, Mock
    import my_module #Also known as my_module.py
    import datetime
    

    然后是实际的测试用例:

    @patch.object(my_module, 'datetime', Mock(wraps=datetime.datetime))
        def testThat_myModule_debouncesEmails(self):
    
            fake_time = datetime.datetime.now()
    
            # This is the first time the thing happened. It should send an email.
            doSomething()
            self.assertEqual(1, emails_sent)
    
            # Five minutes later, the thing happens again. Should be debounced.
            fake_time += datetime.timedelta(minutes=5)
            my_module.datetime.now.return_value = fake_time 
            doSomething()
            self.assertEqual(1, emails_sent)
    
            # Another 56 minutes pass, the thing happens again. An hour has elapsed, so don't debounce.
            fake_time += datetime.timedelta(minutes=56)
            my_module.datetime.now.return_value = fake_time 
            doSomething()
            self.assertEqual(2, emails_sent)
    
            # Give it another 15 minutes to check the debouncing kicks back in.
            fake_time += datetime.timedelta(minutes=15)
            my_module.datetime.now.return_value = fake_time 
            doSomething()
            self.assertEqual(2, emails_sent)
    

    希望这对某人有所帮助!

    【讨论】:

      猜你喜欢
      • 2020-06-11
      • 2012-12-14
      • 2020-11-30
      • 1970-01-01
      • 1970-01-01
      • 2013-12-22
      • 1970-01-01
      • 2017-08-24
      • 2012-10-15
      相关资源
      最近更新 更多