如何模拟深入两个导入的Python类?

Joh*_*n C 5 python unit-testing mocking

如何在不更改任何导入模块中的代码的情况下模拟两个深度导入的Python类?假设我正在导入一个Web实用程序库,它导入一个HTTPClient() - 如何编写单元测试,模拟HTTPClient返回值,而不更改文件web_utils.py?我想在DataHandler中使用数据操作(而不是模拟),但我不希望HTTPClient实际连接到Web.

这甚至可能吗?鉴于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')
Run Code Online (Sandbox Code Playgroud)

更新 - 添加了该get_client()功能.我认为@ spicavigo的答案是在正确的轨道上 - 它似乎取代了这个SomeHTTPClient类.但由于某种原因,类没有实例化一个对象(错误是,"必须是类型,而不是模拟").我不知道它是如何成为一个Mock()已创建的对象,而不是一个类.所以我不确定如何使这部分工作.

spi*_*igo 4

您可以将其添加到 myTest.py 并尝试吗

from someLib import web_utils
web_utils.SomeHTTPClient = <YOUR MOCK CLASS>
Run Code Online (Sandbox Code Playgroud)