python 模拟库 - 用异常替换原始 side_effect 意外失败

问题描述 投票:0回答:1

我想在具有默认 side_effect 的许多测试的类上使用 mock.patch 装饰器,然后在某些特定测试中将该 side_effect 替换为其他行为。当我尝试用异常替换 side_effect 时,模拟代码会引发

TypeError: 'Exception' object is not iterable

请注意,只有在装饰器中使用

autospec=True
时才会发生这种情况。 删除或替换为
spec=my_original_function
时,一切都会按预期工作。 这是 mock 模块上的错误吗?我正在使用版本“1.1.0”

以下是重现问题的方法。

from unittest import TestCase
from mock import patch


def my_original_function():
    return 'my_original_function'


def my_default_side_effect():
    return 'my_default_side_effect'



@patch('tests.my_test.my_original_function', side_effect=my_default_side_effect, autospec=True)
class DebugTest(TestCase):
    def test_default_side_effect_works(self, my_patch):  # This works
        self.assertEqual(my_patch(), 'my_default_side_effect')

    def test_default_side_effect_can_be_replaced_with_new_function(self, my_patch):  # This works
        my_patch.side_effect = lambda: 'some_other_side_effect'
        self.assertEqual(my_patch(), 'some_other_side_effect')

    def test_default_side_effect_can_be_replaced_with_new_list(self, my_patch):  # This works
        my_patch.side_effect = ['other_side_effect_1', 'other_side_effect_2']
        self.assertEqual(my_patch(), 'other_side_effect_1')
        self.assertEqual(my_patch(), 'other_side_effect_2')

    def test_default_side_effect_can_be_replaced_with_new_exception(self, my_patch):  # This fails
        my_patch.side_effect = Exception('exception_side_effect')
        with self.assertRaisesRegex(Exception, 'exception_side_effect'):
            my_patch()
            # AssertionError: "exception_side_effect" does not match "'Exception' object is not iterable"
python unit-testing mocking
1个回答
0
投票

我不确定为什么 autospec=true 会导致错误,但有一种方法可以解决这个问题。只需使用 raise_exception 代替或尝试修改自定义对象。这是一个例子:

from unittest import TestCase
from unittest.mock import patch, Mock

def my_original_function():
    return 'my_original_function'

def my_default_side_effect():
    return 'my_default_side_effect'

def raise_exception(*args, **kwargs):
    raise Exception('exception_side_effect')

@patch('tests.my_test.my_original_function', side_effect=my_default_side_effect, autospec=True)
class DebugTest(TestCase):
    def test_default_side_effect_works(self, my_patch): 
        self.assertEqual(my_patch(), 'my_default_side_effect')

    def test_default_side_effect_can_be_replaced_with_new_function(self, my_patch):  
        my_patch.side_effect = lambda: 'some_other_side_effect'
        self.assertEqual(my_patch(), 'some_other_side_effect')

    def test_default_side_effect_can_be_replaced_with_new_list(self, my_patch):  
        my_patch.side_effect = ['other_side_effect_1', 'other_side_effect_2']
        self.assertEqual(my_patch(), 'other_side_effect_1')
        self.assertEqual(my_patch(), 'other_side_effect_2')

    def test_default_side_effect_can_be_replaced_with_new_exception(self, my_patch):  
        my_patch.side_effect = raise_exception
        with self.assertRaises(Exception) as cm:
            my_patch()
        self.assertEqual(str(cm.exception), 'exception_side_effect')
© www.soinside.com 2019 - 2024. All rights reserved.