简要总结MyClass.my_method
调用了instance = SomeLibrary()
我想创建一个模拟,因此instance
是我可以控制的模拟对象。本着隔离测试的精神,我实际上不想调用SomeLibrary
。
传递给@mock.patch()
的参数
我正在尝试模拟类构造函数,但是我还没有弄清楚要传递给@ mock.patch()装饰器的内容。文档说该参数必须完全加点(pyftdi.ftdi.Ftdi
),但是where to patch
文档说该参数必须与被测试的代码知道它的名称(Ftdi
)相匹配。我看不出如何同时满足这两个条件。
具体来说,这是要测试的文件:
from pyftdi.ftdi import Ftdi
class FtdiInterface(object):
@classmethod
def set_power(cls, url, on):
ftdi = Ftdi()
ftdi.open_from_url(url)
# ... do other things with ftdi
...和测试文件
import unittest
from unittest import mock
from ftdi_interface import FtdiInterface
import pyftdi.ftdi
class TestFtdiInterface(unittest.TestCase):
@mock.patch('pyftdi.ftdi.Ftdi')
def testPowerOn(self, MockFtdi):
url = 'some_string'
ftdi_instance = mock.MagicMock()
ftdi_instance.open_from_url = mock.MagicMock()
MockFtdi.return_value = ftdi_instance
FtdiInterface.set_power(url, True)
ftdi_instance.open_from_url.assert_called_with(url)
我观察到的是,尽管我尝试修补Ftdi(),对
ftdi_instance.open_from_url()
的调用还是调用库代码,而不是我的模拟对象。我想念什么?
最佳答案
Where to patch指出:
基本原理是,您可以在查找对象的位置打补丁,而该对象不一定与定义对象的位置相同。
这意味着要mock
一个类Ftdi
,您必须提供一个路径,以指向代码中实际实例化Ftdi
的位置。
为此,您需要将@mock.patch('pyftdi.ftdi.Ftdi')
替换为@mock.patch('ftdi_interface.Ftdi')
:
import unittest
from unittest import mock
from ftdi_interface import FtdiInterface
class TestFtdiInterface(unittest.TestCase):
@mock.patch('ftdi_interface.Ftdi')
def testPowerOn(self, MockFtdi):
url = 'some_string'
ftdi_instance = mock.MagicMock()
ftdi_instance.open_from_url = mock.MagicMock()
MockFtdi.return_value = ftdi_instance
FtdiInterface.set_power(url, True)
ftdi_instance.open_from_url.assert_called_with(url)
第
import pyftdi.ftdi
行对测试没有任何帮助,可以删除。关于python - mock 一个类(class): catch 22,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/49072847/