例如,如果我调用了split方法(即some_string.split(":"))嘲笑这是可能的。我想断言split函数是使用assert_colled_once_with
我确认你不能这样做,因为split()是str对象的内置属性,你不能设置内置或扩展的属性,因为它们是只读的。
以下是在尝试使用Python 2.7.10解释器后的一些不确定的测试
>>> __builtins__.str.split
<method 'split' of 'str' objects>
>>> type(__builtins__.str.split)
<type 'method_descriptor'>
试图使用功能覆盖它
>>> type(lambda f:f)
<type 'function'>
>>> __builtins__.str.split = lambda f: f
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: can't set attributes of built-in/extension type 'str'
尝试使用可调用(函数或方法)覆盖它
>>> type(callable)
<type 'builtin_function_or_method'>
>>> __builtins__.str.split = callable
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: can't set attributes of built-in/extension type 'str'
在这里对CPython源代码进行了更深入的研究之后[1]。下面的函数列表介绍了Objects/typeobject.c中的一个限制。此函数检查我们是否尝试设置只读属性并引发TypeError。
type_setattro(PyTypeObject *type, PyObject *name, PyObject *value)
{
if (!(type->tp_flags & Py_TPFLAGS_HEAPTYPE)) {
PyErr_Format(
PyExc_TypeError,
"can't set attributes of built-in/extension type '%s'",
type->tp_name);
return -1;
}
if (PyObject_GenericSetAttr((PyObject *)type, name, value) < 0)
return -1;
return update_slot(type, name);
}
[1]https://hg.python.org/cpython/file/tip/Objects/typeobject.c#l3022
是的,它有几个caviat。在我的例子中,我已经成功地在python3中模拟了str,这样我就可以断言split是用特定的输入调用的
有两个空腔
- 使用补丁,我用继承自str的新类替换了原来的str类
- 在我正在测试的代码中,我必须执行像
str(str_val).split
这样的冗余字符串强制转换
以下是如何做到这一点:
class MyStr(str):
def split(self, sep=None, maxsplit=-1)):
expected_str = "some_input_mutated_inside_fn_before_split_called"
self.assertEqual(self, expected_str)
return super().split(sep=sep, maxsplit=maxsplit)
with patch('mymodule.str', new=MyStr):
output = mymodule.function_that_calls_string_split(
"some_input"
)