返回扭曲延迟后,模拟无效

时间:2016-02-25 03:30:32

标签: python unit-testing mocking twisted

我在扭曲的试验单元测试中遇到麻烦。被测试的函数返回一个延迟,我返回从单元测试中推迟的。但是,似乎我已经应用的补丁一旦返回延迟就会被还原,它不会等到延迟解决后。

请参阅以下示例:

schedule.py

import time
from twisted.internet import task, reactor

class Schedule():
    def get_time(self):
        t = time.time()
        return task.deferLater(reactor, 2, lambda: t)

    def get_time_future(self):
        return task.deferLater(reactor, 2, lambda: time.time())

schedule_test.py

import mock
from twisted.trial import unittest
from schedule import Schedule

class ScheduleTest(unittest.TestCase):
    @mock.patch('schedule.time')
    def test_get_time(self, mock_time):
        mock_time.time.return_value = 1450407660
        d = Schedule().get_time()
        d.addCallback(self.assertEqual, 1450407660)
        return d

    @mock.patch('schedule.time')
    def test_get_time_future(self, mock_time):
        mock_time.time.return_value = 1450407660
        d = Schedule().get_time_future()
        d.addCallback(self.assertEqual, 1450407660)
        return d

输出

test_schedule
ScheduleTest
    test_get_time ...                                                      [OK]
    test_get_time_future ...                                             [FAIL]

===============================================================================
[FAIL]
Traceback (most recent call last):
  File "/usr/local/lib/python2.7/dist-packages/twisted/trial/_synctest.py", line 437, in assertEqual
    super(_Assertions, self).assertEqual(first, second, msg)
  File "/usr/lib/python2.7/unittest/case.py", line 515, in assertEqual
    assertion_func(first, second, msg=msg)
  File "/usr/lib/python2.7/unittest/case.py", line 508, in _baseAssertEqual
    raise self.failureException(msg)
twisted.trial.unittest.FailTest: 1456370638.190432 != 1450407660

test_schedule.ScheduleTest.test_get_time_future
-------------------------------------------------------------------------------
Ran 2 tests in 4.024s

FAILED (failures=1, successes=1)

在上面的例子中我嘲笑time的方式有什么问题吗?

2 个答案:

答案 0 :(得分:4)

你嘲笑time的方式确实有问题。 mock装饰器在输入测试函数时设置补丁,然后在退出时删除它们。但是,您返回Deferred,这意味着在测试函数退出后,time.time回调运行良好

如果您只想继续使用类似于模拟的修补界面,可以使用Twisted' TestCase.patch,我认为这会考虑Deferreds

但是,mocking is a testing anti-pattern以及处理时间流逝的更好方法是使用the documented API for testing the passage of timetwisted.internet.task.Clock

答案 1 :(得分:1)

正如Glyph指出的那样,使用TestCase.patch可以提供帮助。补丁需要按如下所示执行:

def test_get_time_future(self):
    mock_time = MagicMock()
    mock_time.time.return_value = 1450407660
    self.patch(sys.modules['schedule'], 'time', mock_time)
    d = Schedule().get_time_future()
    d.addCallback(self.assertEqual, 1450407660)
    return d

此测试通过。