如何在Python单元测试中模拟外部服务器?

如何在Python单元测试中模拟外部服务器?,python,unit-testing,mocking,Python,Unit Testing,Mocking,由于调用外部服务(Twitter、Facebook、Klout等),我有几个单元测试需要很长时间(分钟) 我希望缓存来自这些服务的结果,并以透明的方式提供它们,对我当前的测试进行最小的更改。缓存键取决于URL、查询参数、标题等,因此非常复杂 做到这一点的最佳方法是什么?从技术上讲,如果它使用外部服务,那么它不是一个单元测试,而是一个集成测试。对于单元测试和加速测试代码,请使用模拟对象。您可以在此处找到有关python模拟对象的详细信息: 您通常会(应该)使用某种适配器连接到这些外部服务、模块。这

由于调用外部服务(Twitter、Facebook、Klout等),我有几个单元测试需要很长时间(分钟)

我希望缓存来自这些服务的结果,并以透明的方式提供它们,对我当前的测试进行最小的更改。缓存键取决于URL、查询参数、标题等,因此非常复杂


做到这一点的最佳方法是什么?

从技术上讲,如果它使用外部服务,那么它不是一个单元测试,而是一个集成测试。对于单元测试和加速测试代码,请使用模拟对象。您可以在此处找到有关python模拟对象的详细信息:

您通常会(应该)使用某种适配器连接到这些外部服务、模块。这些是您与外部世界的接口,可以根据场景进行编辑和创建虚假响应


我尝试了许多模拟库,最终发现它们是最适合我的

下面是代码,我们使用请求库调用外部API。因此,我们使用模拟请求对象创建上下文处理器

因此,如果我们测试get_data函数,我们将模拟对外部API的请求:

import requests
import mock
import unittest


def get_data(url):
    resp = requests.get(url)
    return resp

class GetDataTest(unittest.TestCase):

    def test_get_data(self):
        with mock.patch.object(requests, 'get') as get_mock:
            get_mock.return_value = mock_response = mock.Mock()
            mock_response.status_code = 200
            mock_response.content = {'twitter_handle': '@twitter'}
            resp = get_data("http://this_address_does_not_exist.com")
            self.assertEqual(resp.status_code, 200)
            self.assertEqual(resp.content['twitter_handle'], '@twitter')