Avi*_*ohn 4 python unit-testing mocking
autospec=True使用mock.patch及其变体时应何时使用?
一方面,本文警告我们务必使用autospec=True:
...您应始终将
create_autospec方法和autospec参数与@patch和@patch.object装饰器一起使用。
另一方面,autospec正如idjaw对这个问题的回答所解释的那样,它具有严重的缺点和局限性。
所以我的问题是:什么时候应该使用autospec=True或create_autospec,什么时候不应该使用它?
我担心不使用它autospec可能导致测试在真正应该中断时不会中断,如所述文章所述。但是autospec有其缺点。我该怎么办?
我可以理解建议使用的动机autospec。
也许以下内容可以帮助您更清楚地了解使用autospec获得和不获得的内容。
简而言之,使用autospec可以确保您在模拟中使用的属性实际上属于您要模拟的类的一部分。
因此,在下面的示例中,我将说明在技术上您可能不希望测试通过时如何通过测试:
举这个简单的例子,我们将测试:
class Foo:
def __init__(self, x):
self.x = x
class Bar:
def __init__(self):
self.y = 4
self.c = Foo('potato')
Run Code Online (Sandbox Code Playgroud)
和测试代码:
class TestAutoSpec(unittest.TestCase):
@patch('some_module.Foo')
def test_autospec(self, mock_foo_class):
mock_foo_obj = mock_foo_class.return_value
bar_obj = some_module.Bar()
self.assertTrue(hasattr(bar_obj.c, 'you_should_fail'))
Run Code Online (Sandbox Code Playgroud)
现在,如果您回顾一下Foo该类,您将清楚地看到you_should_fail显然不是中的属性Foo。但是,如果您运行此测试代码,则它实际上会通过。这是非常误导的。
这是因为如果一个属性不以存在MagicMock,这将仍然是类型MagicMock。如果type(bar_obj.c.you_should_fail)在该测试中打印,最终将得到:
<class 'unittest.mock.MagicMock'>
Run Code Online (Sandbox Code Playgroud)
这肯定会导致hasattr测试通过。如果您再次运行上述测试,除了改变你的补丁是:@patch('some_module.Foo', autospec=True),它会失败,因为它应该。
现在,要为此编写成功的测试并仍然使用autospec = True,只需在所需的模拟测试中创建属性。请记住,之所以需要这样做,是因为autospec无法得知动态创建的属性,即在__init__创建实例时。
因此,执行此操作的自动规格方式为:
class TestAutoSpec(unittest.TestCase):
@patch('some_module.Foo', autospec=True)
def test_autospec(self, mock_foo_class):
mock_foo_obj = mock_foo_class.return_value
# create the attribute you need from mocked Foo
mock_foo_obj.x = "potato"
bar_obj = some_module.Bar()
self.assertEqual(bar_obj.c.x, 'potato')
self.assertFalse(hasattr(bar_obj.c, 'poof'))
Run Code Online (Sandbox Code Playgroud)
现在,您的测试将成功通过验证您的x属性,同时还验证您没有真实Foo类中不存在的虚假属性。
这也是Martijn Pieters的另一种解释,它不一定直接回答您的问题,但是提供了一个很好的示例和使用autospec的解释,可以帮助您进一步理解:
| 归档时间: |
|
| 查看次数: |
2137 次 |
| 最近记录: |