在使用autospec=True及其变体时,我应该何时使用mock.patch?一方面,this article警告我们始终使用autospec=True:…你应该总是使用create_autospec方法和autospec参数和@patch和@patch.object装饰器。另一方面,autospec有严重的缺点和局限性,正如idjaw对this question的回答所解释的那样。所以我的问题是:什么时候应该使用autospec=True或create_autospec,什么时候不应该使用它?我担心不使用autospec可能会导致测试在真正应该中断时不中断,如上述文章所述。然而autospec也有其缺点。我该怎么做? 最佳答案 我可以理解建议使用的动机。也许下面的内容可以帮助你更清楚地了解你所得到的,而不是用AutoPoC得到的。简而言之,使用autospec可以确保在模拟中使用的属性实际上是模拟类的一部分。因此,通过下面的示例,我将说明在技术上您可能不希望测试通过时,测试将如何通过:举个简单的例子,我们将测试:class Foo: def __init__(self, x): self.x = xclass Bar: def __init__(self): self.y = 4 self.c = Foo('potato')测试代码: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'))现在,如果回头看autospec类,你会清楚地看到Foo显然不是you_should_fail中的属性。但是,如果运行此测试代码,它实际上将通过。这是很误导人的。这是因为如果一个属性不存在于Foo,它仍然是类型MagicMock。如果您在测试中打印MagicMock,您将得到:<class 'unittest.mock.MagicMock'>这肯定会导致type(bar_obj.c.you_should_fail)测试通过。如果您再次运行上述测试,除了更改您的补丁为:hasattr,它将失败,因为它应该。现在,要为此编写一个成功的测试并仍然使用autospec=true,只需根据需要在模拟测试中创建属性。记住,之所以需要这样做,是因为autospec无法知道动态创建的属性,即在创建实例时在@patch('some_module.Foo', autospec=True)中创建的属性。所以,autospec的方法是: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'))现在,您的测试将成功通过验证您的__init__属性,同时也验证您没有真正的x类中不存在的一些伪属性。这也是Martijn Pieters的另一个解释,它不一定直接回答你的问题,但是给出了一个很好的例子,说明了使用AutoPoC可以帮助你进一步理解:https://stackoverflow.com/a/31710001/1832539
09-27 04:35