返回扭曲的延迟后模拟无效
Mock is not effective after twisted deferred is returned
我在扭曲试验单元测试中遇到模拟问题。被测函数 return 被推迟了,而我 return 从单元测试中推迟了。但是,一旦我 return 延迟,我应用的补丁似乎就被还原了,它不会等到延迟被解决。
请看下面的例子:
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
的方式有什么问题吗?
你嘲讽的方式确实有问题time
。 mock
装饰器在进入测试函数时设置补丁,然后在退出时删除它们。但是,您返回的是 Deferred
,这意味着 time.time
回调运行良好 在 测试函数退出后。
如果您只想继续使用类似模拟的修补界面,您可以使用 Twisted 的 TestCase.patch
,我相信它会 Deferreds
考虑在内。
然而,mocking is a testing anti-pattern, and a much better way to deal with the passage of time is to use the documented API for testing the passage of time, twisted.internet.task.Clock
.
因为 Glyph pointed out, using 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
此测试通过。
我在扭曲试验单元测试中遇到模拟问题。被测函数 return 被推迟了,而我 return 从单元测试中推迟了。但是,一旦我 return 延迟,我应用的补丁似乎就被还原了,它不会等到延迟被解决。
请看下面的例子:
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
的方式有什么问题吗?
你嘲讽的方式确实有问题time
。 mock
装饰器在进入测试函数时设置补丁,然后在退出时删除它们。但是,您返回的是 Deferred
,这意味着 time.time
回调运行良好 在 测试函数退出后。
如果您只想继续使用类似模拟的修补界面,您可以使用 Twisted 的 TestCase.patch
,我相信它会 Deferreds
考虑在内。
然而,mocking is a testing anti-pattern, and a much better way to deal with the passage of time is to use the documented API for testing the passage of time, twisted.internet.task.Clock
.
因为 Glyph pointed out, using 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
此测试通过。