为什么monkeypatching os.path需要路径参数?

时间:2016-12-22 01:03:29

标签: python pytest monkeypatching

pytest在monkeypatching文档中有此示例:

import os.path
def getssh(): # pseudo application code
    return os.path.join(os.path.expanduser("~admin"), '.ssh')

def test_mytest(monkeypatch):
    def mockreturn(path):
        return '/abc'
    monkeypatch.setattr(os.path, 'expanduser', mockreturn)
    x = getssh()
    assert x == '/abc/.ssh'

当我从path函数中删除mockreturn参数时,出现错误

    def getssh():  # pseudo application code
>       return os.path.join(os.path.expanduser("~admin"), '.ssh')
E       TypeError: mockreturn() takes 0 positional arguments but 1 was given

我不明白提供这种位置论证的是什么?

另外,当我为pathlib.Path.home()重新实现同样的东西时,我不能在那里使用这个参数path,否则它不会起作用。不幸的是,文档没有说明这个不祥的path论点。

对于这里发生什么魔法的任何照明都会非常有帮助!

1 个答案:

答案 0 :(得分:1)

您正在尝试将一个参数替换os.path.expanduser替换为一个不会引用参数的模拟,这些参数在调用时会导致错误。 引擎monkeypatch.setattr使用内置setattr,因此原始版本基本上可以执行以下操作,因为expandusermock都采用单个参数:

>>> import os.path
>>> def mock(path):
...     return '/abc'
... 
>>> setattr(os.path, 'expanduser', mock)
>>> os.path.expanduser('~admin')
'/abc'

现在,如果您尝试使用不接受参数的方法替换expanduser并继续调用它,就像您收到错误一样:

>>> setattr(os.path, 'expanduser', mock)
>>> os.path.expanduser('~admin')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: mock() takes 0 positional arguments but 1 was given

请注意,如果您尝试直接致电mock,则会收到完全相同的错误:

>>> mock('~admin')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: mock() takes 0 positional arguments but 1 was given