在py.test monkeypatching/mocking documentation中没有提及,但是可以对函数体中引入的局部变量进行monkeypatch?
我的实验:
def my_method():
my_var = 'foo'
return my_var[:2]
测试是:
def test_my_method(monkeypatch):
monkeypatch.setattr(my_module.MyClass.my_method.my_var, lambda: 'bar')
assert my_method() == 'ba'
AttributeError:MyClass.my_method中的'function'对象没有 属性'my_var'
答案 0 :(得分:6)
这是不可能的,因为变量不会提前存在,并且就我所知,py.test无法挂钩创建局部变量。
答案 1 :(得分:3)
稍加注意,就有可能使用ctypes在功能代码对象中修补const。
import ctypes
from contextlib import contextmanager
def tuple_setitem(tup, index, item):
obj = ctypes.py_object(tup)
item = ctypes.py_object(item)
ref_count = ctypes.c_long.from_address(id(tup))
original_count = ref_count.value
if original_count != 1:
ref_count.value = 1
ctypes.pythonapi.Py_IncRef(item)
ctypes.pythonapi.PyTuple_SetItem(obj, ctypes.c_ssize_t(index), item)
ref_count.value = original_count
@contextmanager
def patch_tuple_item(tup, index, item):
old = tup[index]
try:
tuple_setitem(tup, index, item)
yield
finally:
tuple_setitem(tup, index, old)
演示:
>>> def my_method():
... my_var = "foo"
... return my_var[:2]
...
>>> consts = my_method.__code__.co_consts
>>> consts
(None, 'foo', 2)
>>> with patch_tuple_item(consts, index=1, item="bar"):
... print(my_method())
...
ba
>>> print(my_method())
fo