Python 为什么要使用补丁装饰程序而不是显式实例化的MagicMock?
所以最近在Python中,我开始使用unittest库。但是,有一件事我无法理解(我已经试着查找了好几个小时了……)那就是为什么要在显式MagicMock对象上使用补丁装饰器 更具体地说,下面是我试图测试的代码。一些简要说明:Python 为什么要使用补丁装饰程序而不是显式实例化的MagicMock?,python,unit-testing,mocking,Python,Unit Testing,Mocking,所以最近在Python中,我开始使用unittest库。但是,有一件事我无法理解(我已经试着查找了好几个小时了……)那就是为什么要在显式MagicMock对象上使用补丁装饰器 更具体地说,下面是我试图测试的代码。一些简要说明: 该代码试图测试某个餐厅的简单菜单类 在setUp方法中,我通过存储一些实例化的食物对象(在本例中被MagicMock对象替换)来准备实例化的菜单对象 在testFindItem方法中,我试图通过搜索食物对象的名称,从菜单中查找并返回食物对象。然后我将找到的对象与假定的食
- 该代码试图测试某个餐厅的简单菜单类
- 在
方法中,我通过存储一些实例化的食物对象(在本例中被MagicMock对象替换)来准备实例化的菜单对象setUp
- 在
方法中,我试图通过搜索食物对象的名称,从菜单中查找并返回食物对象。然后我将找到的对象与假定的食物对象(本例中为MagicMock对象)进行比较testFindItem
设置
方法中,我是如何将self.bread
和self.carboard
替换为MagicMock对象而不是食物对象的。代码是有效的,这很好,但另一种选择是使用覆盖Food类的补丁装饰器
TL;DR:为什么在这种情况下(即使用补丁)会更好还是更糟?或者更确切地说,正如前面提到的,为什么要在显式MagicMock对象上使用补丁装饰器
哦,顺便说一句,我找到的最接近的答案是另一篇文章,它讨论了补丁和模拟的区别,但没有讨论为什么你会使用一个而不是另一个:
这不是补丁的用例。使用该选项的原因是要替换在别处定义的对象。在这里,您显式地实例化了菜单,并传入了您想要调用断言的内容,所以补丁是没有用的;但是有很多时候,被测试的类会创建自己的对象,或者从代码的其他部分获取它们,而这正是使用补丁的时候。这不是补丁的用例。使用该选项的原因是要替换在别处定义的对象。在这里,您显式地实例化了菜单,并传入了您想要调用断言的内容,所以补丁是没有用的;但是,很多时候,当被测试的类创建自己的对象,或者从代码的其他部分获取对象时,您会使用patch。当您修补现有代码时,您使用patch,而您只是将mock作为参数传递。这就是为什么你看不到好处;没有。你考虑过阅读
mock
文档吗?@jornsharpe啊,我明白了。另外,如果你在这里指的是:,那么是的,很多次了,但我还是觉得很难理解。我否决了这个问题,因为即使它是正确的,写得很好,它也只会制造噪音,而且没有给予任何好的评价。这个问题可以用“如果我不需要补丁,为什么我应该使用它?”来概括。我希望TL;DR的声明将解决这个问题,也许不是。另外,直到Roseman回答之后,我才意识到修补程序本身是不必要的。修补现有代码时使用修补程序,而只是将模拟作为参数传递。这就是为什么你看不到好处;没有。你考虑过阅读mock
文档吗?@jornsharpe啊,我明白了。另外,如果你在这里指的是:,那么是的,很多次了,但我还是觉得很难理解。我否决了这个问题,因为即使它是正确的,写得很好,它也只会制造噪音,而且没有给予任何好的评价。这个问题可以用“如果我不需要补丁,为什么我应该使用它?”来概括。我希望TL;DR的声明将解决这个问题,也许不是。而且,直到Roseman回答之后,我才意识到补丁本身是不必要的。
class MenuTest(unittest.TestCase):
"""
Unit test class for Menu class.
"""
def setUp(self):
"""
Prepares a menu to be tested against using mock objects.
"""
self.bread = MagicMock()
self.cardboard = MagicMock()
self.bread.name = "bread"
self.cardboard.name = "cardboard"
foodItems = [self.cardboard, self.bread]
self.menu = Menu(foodItems)
def testFindItem(self):
"""
Tests whether a specified food item can be found on the menu.
"""
# Items on the menu
self.assertEqual(self.menu.findItem("bread"), self.bread)
self.assertEqual(self.menu.findItem("cardboard"), self.cardboard)
# Items not on the menu
with self.assertRaises(NameError):
self.menu.findItem("salvation")