如何Mock Queue.__next__魔法方法?side_effect失效问题解决
问题原因
Python执行for msg in self._queue时,会先调用self._queue.__iter__()获取迭代器对象,再对该迭代器调用__next__()。你用MagicMock创建的queue对象,默认__iter__方法会返回一个全新的Mock实例,而非queue本身。因此你设置的queue.__next__.side_effect根本不会被触发,遍历实际使用的是__iter__返回的Mock实例的__next__方法。
解决方法
有两种可行的修复方式:
方法一:让__iter__返回Mock对象自身
指定queue的__iter__方法返回自身,这样遍历过程中就会调用你预先设置的__next__方法:
def test_it(): queue = MagicMock() queue.__iter__.return_value = queue # 核心:让迭代器返回自身 queue.__next__.side_effect = [4, 5, 6] consumer = Consumer(queue) try: consumer.consume() except ValueError as e: assert str(e) == "4" # 验证首次遍历抛出的异常值符合预期
方法二:给__iter__返回的迭代器单独设置__next__
如果不需要__iter__返回自身,可以直接为__iter__返回的Mock实例配置__next__的side_effect:
def test_it(): queue = MagicMock() iter_mock = MagicMock() iter_mock.__next__.side_effect = [4, 5, 6] queue.__iter__.return_value = iter_mock consumer = Consumer(queue) try: consumer.consume() except ValueError as e: assert str(e) == "4"
补充说明
测试中建议添加异常捕获逻辑,因为你的consume方法每次遍历都会抛出ValueError,第一次循环就会终止,通过断言首次抛出的异常值,就能验证模拟逻辑是否生效。
内容的提问来源于stack exchange,提问作者Альберт Александров
相关产品推荐
相关产品推荐

