要创建给定函数的单元测试,我需要修补”.join(…).
我已经尝试了很多方法(使用mock库),但即使我有一些使用该库创建单元测试的经验,我也无法让它工作.
出现的第一个问题是str是一个内置类,因此它不能被嘲笑. A post by William John Bert显示了如何处理这个问题(在他的情况下是datetime.date).图书馆官方文档的“Partial mocking” section中也有可能的解决方案.
第二个问题是str并没有真正直接使用.相反,调用文字”的方法连接.那么,补丁的路径应该是什么?
这些选项都不起作用:
> patch(‘__ builtin __.str’,’join’)
> patch(‘string.join’)
> patch(‘__ builtin __.str’,FakeStr)(其中FakeStr是str的子类)
任何帮助将不胜感激.
最佳答案 你不能,因为无法在内置类中设置属性:
>>> str.join = lambda x: None
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: can't set attributes of built-in/extension type 'str'
并且你不能修补str,因为’.join使用文字,因此无论你如何尝试在__builtin__中替换str,解释器总是会创建一个str.
如果您读取生成的字节码,您可以看到这个:
>>> import dis
>>> def test():
... ''.join([1,2,3])
...
>>> dis.dis(test)
2 0 LOAD_CONST 1 ('')
3 LOAD_ATTR 0 (join)
6 LOAD_CONST 2 (1)
9 LOAD_CONST 3 (2)
12 LOAD_CONST 4 (3)
15 BUILD_LIST 3
18 CALL_FUNCTION 1
21 POP_TOP
22 LOAD_CONST 0 (None)
25 RETURN_VALUE
字节码是在编译时生成的,正如您所看到的,无论您在运行时如何更改str的值,第一个LOAD_CONST都会加载”,这是一个str.
你可以做的是使用一个可以模拟的包装函数,或者避免使用文字.
例如,使用str()而不是”允许您使用实现连接方法的子类来模拟str类(尽管这可能会影响太多代码,并且根据您使用的模块可能不可行).