如何使用模拟库修补方法”.join

要创建给定函数的单元测试,我需要修补”.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类(尽管这可能会影响太多代码,并且根据您使用的模块可能不可行).

点赞