如何模拟一个名为默认参数的函数

时间:2016-04-01 09:27:14

标签: python-3.x mocking python-unittest

我有一个包含时间戳的类。在init函数中,初始时间戳设置为提供的参数,默认值为' time.monotonic()'。我也有更新功能来设置时间戳,也使用time.monotonic()

在对这个类进行单元测试时,我想模拟出time.monotonic,以获得可预测的结果。

但是,默认参数中的调用始终是实时的。单调

ClassWithTimestamp.py:

import time

class ClassWithTimestamp:
    def __init__(self, value={}, timestamp=time.monotonic()):
        self.timestamp = timestamp

    def update(self):
        self.timestamp = time.monotonic()

ClassWithTimestampTest.py:

import unittest
from unittest import mock

import ClassWithTimestamp

class ClassWithTimestampTest(unittest.TestCase):
    def setUp(self):
        ClassWithTimestamp.time.monotonic = mock.Mock(name='now')
        ClassWithTimestamp.time.monotonic.return_value = 1000

    def tearDown(self):
        pass

    def test_init(self):
        sut = ClassWithTimestamp.ClassWithTimestamp()
        self.assertEqual(sut.timestamp, 1000)

    def test_update(self):
        sut = ClassWithTimestamp.ClassWithTimestamp()
        sut.update()
        self.assertEqual(sut.timestamp, 1000)

if __name__ == '__main__':
    unittest.main()

运行时:

python3 ClassWithTimestampTest.py -v
test_init (__main__.ClassWithTimestampTest) ... FAIL
test_update (__main__.ClassWithTimestampTest) ... ok

======================================================================
FAIL: test_init (__main__.ClassWithTimestampTest)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "ClassWithTimestampTest.py", line 16, in test_init
    self.assertEqual(sut.timestamp, 1000)
AssertionError: 762811.874163785 != 1000

----------------------------------------------------------------------
Ran 2 tests in 0.001s

FAILED (failures=1)

1 个答案:

答案 0 :(得分:0)

我发现了这个:

"Least Astonishment" and the Mutable Default Argument

它解释了我的问题,默认参数在定义init函数时调用,而不是执行它。

因为我打算将时间戳设置为构建时间,所以我的代码开始有问题。

我的修改后的代码是

def __init__(self, value={}, timestamp=None):
    if timestamp:
        self.timestamp = timestamp
    else:
        self.timestamp = time.monotonic()

问题本身仍然存在,我看到的唯一方法是在构造后用模拟函数的输出覆盖类的成员。