Python 3.6中是否可以模拟内置的len()
函数?
我有一个类,定义了一个简单的方法,依赖于len()
函数,如下所示:
class MyLenFunc(object):
def is_longer_than_three_characters(self, some_string):
return len(some_string) > 3
我尝试为这个方法编写单元测试,但是当我试图模拟 len()
函数时,会导致出现错误。
以下是我的部分代码:
import unittest
from unittest.mock import patch
import my_len_func
class TestMyLenFunc(unittest.TestCase):
@patch('builtins.len')
def test_len_function_is_called(self, mock_len):
# Arrange
test_string = 'four'
# Act
test_object = my_len_func.MyLenFunc()
test_object.is_longer_than_three_characters(test_string)
# Assert
self.assertEqual(1, mock_len.call_count)
if __name__ == '__main__':
unittest.main()
我在这里找到了另一个关于SO的问题/答案(链接),它表明无法模拟内置函数,因为它们是不可变的。但是,我在这里和这里发现了更多的网站,它们提出了相反的观点。我尝试使用上述单元测试类,直接从后者的网站中获取(是的,我尝试过其中提到的其他技术,但最终都以相同的错误结束)。
我遇到的错误太长了,无法完整贴出,因此我将剪辑掉其中重复的部分(您将看到它从错误消息的最终部分递归)。错误文本如下:
ERROR: test_len_function_is_called (__main__.TestMyLenFunc)
----------------------------------------------------------------------
Traceback (most recent call last):
File "C:\Python36\Lib\unittest\mock.py", line 1179, in patched
return func(*args, **keywargs)
File "C:/Python/scratchpad/my_len_func_tests.py", line 16, in test_len_function_is_called
test_object.is_longer_than_three_characters(test_string)
File "C:\Python\scratchpad\my_len_func.py", line 3, in is_longer_than_three_characters
return len(some_string) > 3
File "C:\Python36\Lib\unittest\mock.py", line 939, in __call__
return _mock_self._mock_call(*args, **kwargs)
File "C:\Python36\Lib\unittest\mock.py", line 949, in _mock_call
_call = _Call((args, kwargs), two=True)
File "C:\Python36\Lib\unittest\mock.py", line 1972, in __new__
_len = len(value)
...
(Repeat errors from lines 939, 949, and 1972 another 95 times!)
...
File "C:\Python36\Lib\unittest\mock.py", line 939, in __call__
return _mock_self._mock_call(*args, **kwargs)
File "C:\Python36\Lib\unittest\mock.py", line 944, in _mock_call
self.called = True RecursionError: maximum recursion depth exceeded while calling a Python object
----------------------------------------------------------------------
Ran 1 test in 0.004s
FAILED (errors=1)
非常感谢您的预先帮助。
__len__()
方法吗? - Eric Duminillen()
不是这样的方法。你确实可以只替换builtins
上的引用,以使用不同的实现来替换它。但对于str.count
等方法,你不能这样做。 - Martijn PietersAttributeError: <module 'builtins' (built-in)> does not have the attribute '__len__'
。 - DatHydroGuy__len__
的对象(因为对于自定义 Python 类的实例,len(ob)
调用的是type(ob).__len__(ob)
)。然而,这会使事情变得不必要地复杂,因为现在你需要在一个模拟对象中模拟所有其他str
提供的操作和你的代码所需的操作,以替换你传入的字符串。 - Martijn Pietersstr
中获得额外的功能。 - DatHydroGuy