如何在不更改任何一个导入模块中的代码的情况下模拟两个深度导入的 Python 类?假设我正在导入一个 Web 实用程序库,该库导入一个 HTTPClient() - 我如何编写一个单元测试,模拟 HTTPClient 以返回一个值,而不更改文件 web_utils.py?我想在 DataHandler 中使用数据操作(而不是模拟出来),但我不希望 HTTPClient 实际连接到网络。
这甚至可能吗?鉴于 Python 有猴子补丁,它当然看起来应该是。还是有替代/更好的方法?我仍在弄清楚模拟过程,更不用说改变进口了。
# someLib/web_utils.py
from abc.client import SomeHTTPClient # the class to replace
def get_client():
tc = SomeHTTPClient(endpoint='url') # fails when I replace the class
return tc
class DataHandler(object):
def post_data(someURL, someData):
newData = massage(someData)
client = get_client()
some_response = client.request(someURL, 'POST', newData)
return some_response
# code/myCode.py
from someLib.web_utils import DataHandler
dh = DataHandler()
reply = dh.post_data(url, data)
# tests/myTests.py
from django.test.testcases import TestCase
from mock import Mock
class Mocking_Test(TestCase):
def test_mock(self):
from someLib import web_utils
fakeClient = Mock()
fakeClient.request = web_utils.SomeHTTPClient.request # just to see if it works
web_utils.SomeHTTPClient = fakeClient
dh = DataHandler()
reply = dh.post_data(url='somewhere', data='stuff')
更新 - 添加了该get_client()
功能。我认为@spicavigo 的答案在正确的轨道上——它似乎确实正在取代SomeHTTPClient
课程。但由于某种原因,该类没有实例化一个对象(错误是,“必须是类型,而不是 Mock”)。我也看不出它是如何成为一个Mock()
已创建的对象,而不是一个类。所以我不确定如何使这部分工作。