2016-02-25 1 views
2

У меня возникли проблемы с насмешкой в ​​скрученном пробном модульном тесте. Функция, находящаяся под тестированием, возвращает отложенную дату, и я возвращаю ее, отложенную из модульного теста. Тем не менее, кажется, что исправления, которые я применил, возвращаются, как только я возвращаю отложенные, он не ждет, пока отложенные решения не будут решены.Mock недействителен после возврата отложенной отсрочки

Пожалуйста, смотрите следующий пример:

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 в приведенном выше примере?

ответ

3

Вроде бы что-то не так, как вы насмешливо time. Декоратор mock устанавливает патчи на входе в тестовую функцию, а затем удаляет их при выходе. Но вы возвращаете Deferred, что означает, что обратный вызов time.time работает хорошо после, после чего завершилась тестовая функция.

Если вы хотите продолжить использовать макетный интерфейс исправления, вы можете использовать TestCase.patch Twisted, который, как я полагаю, займет Deferreds.

Однако, mocking is a testing anti-pattern, и гораздо лучший способ справиться с течением времени - использовать the documented API for testing the passage of time, twisted.internet.task.Clock.

+0

«время» - это просто пример, но это не всегда «время», которое я хочу высмеять. 'TestCase.patch' действительно помог решить проблему. Я должен был исправить его как 'self.patch (sys.modules ['schedule'], 'time', mock_time)' –

+1

@AjmalA вы должны положить это как ответ, это хорошая находка. – idjaw

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 

Этот тест проходит.