gpt4 book ai didi

python - Pytest:模拟具有不同 side_effect 的相同方法的多次调用

转载 作者:行者123 更新时间:2023-12-04 16:45:09 25 4
gpt4 key购买 nike

我有一个像下面这样的单元测试:

# utilities.py  
def get_side_effects():
def side_effect_func3(self):
# Need the "self" to do some stuff at run time.
return {"final":"some3"}

def side_effect_func2(self):
# Need the "self" to do some stuff at run time.
return {"status":"some2"}

def side_effect_func1(self):
# Need the "self" to do some stuff at run time.
return {"name":"some1"}

return side_effect_func1, side_effect_func2, side_effect_func2

#################

# test_a.py
def test_endtoend():

s1, s2, s3 = utilities.get_side_effects()

m1 = mock.MagicMock()
m1.side_effect = s1

m2 = mock.MagicMock()
m2.side_effect = s2

m3 = mock.MagicMock()
m3.side_effect = s3

with mock.patch("a.get_request", m3):
with mock.patch("a.get_request", m2):
with mock.patch("a.get_request", m1):
foo = a() # Class to test
result = foo.run()


作为 foo.run() 的一部分代码运行, get_request被多次调用。我想为 get_request 的每次调用使用不同的 side_effect 函数方法,在这种情况下是 side_effect_func1 , side_effect_func2 , side_effect_func3 .但我注意到只有 m1模拟对象是事件的,即只有 side_effect_func1被调用而不是其他 2. 我如何实现这一目标?
我也尝试了下面的方法,但是没有调用实际的 side_effect 函数,它们总是返回 function object ,但实际上并不执行 side_effect 函数。
# utilities.py
def get_side_effects():
def side_effect_func3(self):
# Need the "self" to do some stuff at run time.
return {"final":"some3"}

def side_effect_func2(self):
# Need the "self" to do some stuff at run time.
return {"status":"some2"}

def side_effect_func1(self):
# Need the "self" to do some stuff at run time.
return {"name":"some1"}

all_get_side_effects = []
all_get_side_effects.append(side_effect_func1)
all_get_side_effects.append(side_effect_func2)
all_get_side_effects.append(side_effect_func3)

return all_get_side_effects

#########################
# test_a.py
def test_endtoend():

all_side_effects = utilities.get_side_effects()

m = mock.MagicMock()
m.side_effect = all_side_effects

with mock.patch("a.get_request", m):
foo = a() # Class to test
result = foo.run()

最佳答案

您的第一次尝试不起作用,因为每个模拟只是替换了前一个(外面的两个模拟什么也不做)。
您的第二次尝试不起作用,因为副作用被重载以用于可迭代对象的不同目的( docs ):

If side_effect is an iterable then each call to the mock will return the next value from the iterable.


相反,您可以使用一个可调用的类来实现副作用,该类连续地维护有关实际调用哪个底层函数的某种状态。
具有两个函数的基本示例:
>>> class SideEffect:
... def __init__(self, *fns):
... self.fs = iter(fns)
... def __call__(self, *args, **kwargs):
... f = next(self.fs)
... return f(*args, **kwargs)
...
>>> def sf1():
... print("called sf1")
... return 1
...
>>> def sf2():
... print("called sf2")
... return 2
...
>>> def foo():
... print("called actual func")
... return "f"
...
>>> with mock.patch("__main__.foo", side_effect=SideEffect(sf1, sf2)) as m:
... first = foo()
... second = foo()
...
called sf1
called sf2
>>> assert first == 1
>>> assert second == 2
>>> assert m.call_count == 2

关于python - Pytest:模拟具有不同 side_effect 的相同方法的多次调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64992044/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com