Python 在第一次调用后引发异常

Python 在第一次调用后引发异常,python,django,mocking,magicmock,Python,Django,Mocking,Magicmock,我有一个循环,处理向zip文件添加记录。我已经模拟了我的zipfile对象,我想引发一个异常,以验证我处理大型zipfile的逻辑是否正常工作 magicmock或普通Mock是否有办法接受第一个调用,但在第二个调用时引发异常?具有生成器和Mock副作用 from unittest.mock import Mock def sample_generator(): yield 1 yield 2 raise Exception() gen = sample_genera

我有一个循环,处理向zip文件添加记录。我已经模拟了我的zipfile对象,我想引发一个异常,以验证我处理大型zipfile的逻辑是否正常工作


magicmock或普通Mock是否有办法接受第一个调用,但在第二个调用时引发异常?

具有生成器和Mock副作用

from unittest.mock import Mock

def sample_generator():
    yield 1
    yield 2
    raise Exception()

gen = sample_generator()

def sideeffect():
    global gen
    for x in gen:
        return x


m = Mock(side_effect=sideeffect)
m() #1
m() #2
m() #3
你可以得到:

File "test.py", line 22, in <module>
   m() #3
   ....
   raise Exception()
Exception
文件“test.py”,第22行,在
m()#3
....
引发异常()
例外情况

我相信您可以通过一些努力使它稍微干净一些,但它应该可以解决您的基本问题

最简单的方法是使用接受iterable、callable或Exception(类或实例)的

或者,
副作用
可以是异常类或实例。在这种情况下,调用mock时将引发异常

如中所示,您可以使用
副作用
通过

此外,您可以在
副作用
赋值中同时使用列表和异常。所以做你需要的事情最简单的方法是:

>>> m = Mock(side_effect=[1, KeyError("bar"), 3])
>>> m("a")
1
>>> m("b")
 ...
KeyError: 'bar'
>>> m("c")
3

另一种方法是使用callable来编写模拟应该如何反应的逻辑。在这种情况下,您可以根据参数或测试状态自由选择。

shot,允许第一次调用,并在第二次调用时抛出,但是,如果我想让第三次通话成功怎么办?@Nathantergillus看一下我的回答,它也包含了你的评论。我没有编辑你的回答来包含OP请求,只是因为我应该对它做太多更改。我以前做过。所以填写了一个新的答案。@Micheled'Amico请随意编辑您的观点,它更简单,并且涵盖了OP要求的两种情况。顺便说一句,否决投票不是我的工作……说真的。我讨厌人们那样做!我喜欢你的回答!这个关键错误,这是一个特殊的方法吗?我想让它抛出一个特定的异常,有没有办法做到这一点?@Nathanteregillus我使用了
KeyError
作为示例。您可以使用任何类型的
异常
。@maazza是的,当然
m
是模拟对象。即使你指的是一个修补过的对象,答案也是肯定的:
patch
用一个
Mock
实例修补一个对象。修补时,你需要这样定义副作用
m.side\u effect=[1,keyrerror(),3]
>>> m = Mock(side_effect=[1, KeyError("bar"), 3])
>>> m("a")
1
>>> m("b")
 ...
KeyError: 'bar'
>>> m("c")
3