在您的代码中模拟出API调用
使用任何积极开发的(python)编码项目,您都可以’re和您的团队每周将进行数百次相同的曾夫人论坛。如果有’向那里的任何第三方资源发出HTTP请求,这可能会导致问题。 API调用可能会很昂贵,过多地刮擦同一源可能会导致IP黑名单,并且调用可能会减慢整个曾夫人论坛过程的速度,从而给代码部署过程增加了负担。
为了解决这个问题,我们可以使用Python’的模拟库。模拟对于创建伪函数调用,伪类和其他可以返回伪值的伪对象非常有用。在大多数情况下,进行曾夫人论坛时,您实际上实际上是在曾夫人论坛应用程序如何解析数据,而不是第三方服务的可靠性。 API’的响应通常是相同的。模拟可以让您模拟API’响应并解析其数据,而不必每次都真正拨打电话。
It’设置起来非常棘手,所以我想我会写一个教程。情况设置有几个组成部分,但我’我会尽量解释一下。让’s说有一个提供一些有用的API响应的服务。那里’是一个由肯尼斯·雷茨(Kenneth Reitz)设置的网站HTTPBin,用于曾夫人论坛HTTP库,我们将在这里使用它。签出: //httpbin.org/ip内容如下:
1 2 3 |
{ “起源”: “ 123.123.123.123”, } |
让’s说我们的程序想获取IP地址中的 起源 领域。对–一个毫无意义的程序,但这类似于您的许多情况’ll encounter.
这里’是一个完全过度设计的类,无法从此服务获取数据。在类中初始化时 __在里面__,它将创建一个指向HTTPBin的base_url变量。主要的处理程序功能是 得到_ip功能,只需抓住那个领域’的内容。首先拨打电话 api_call 使用 request.get 获取该HTTP数据。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
从 要求 进口 得到 类 我的课: 定义 __在里面__(自): 自.base_url = "//httpbin.org/ip" 定义 api_call(自): “”“进行API调用”“” 结果 = 得到(自.base_url) 如果 结果.好: 返回 结果.json() 返回 假 定义 得到_ip(自): “”“从API响应中获取语言”“” 尝试: 数据 = 自.api_call() 返回 数据['起源'] 除 (TypeError, KeyError, IndexError): 返回 “对{0}的HTTP请求失败”.格式(自.base_url) |
要简单地运行此代码(在Python Shell中):
1 2 3 4 |
>>> 进口 my_module >>> 曾夫人论坛 = my_module.我的课() >>> 曾夫人论坛.得到_ip() u'123.123.123.123' |
如果我们要模拟出来怎么办 request.get? 嘲笑模块文档尚不清楚如何在类中深入定位特定功能。事实证明,最简单的方法不是 魔术模拟 要么 返回_value 而是使用反直觉的命名 “副作用”特征。这是曾夫人论坛模块的预模拟:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
进口 单元曾夫人论坛 从 my_module 进口 我的课 类 曾夫人论坛分类器(单元曾夫人论坛.曾夫人论坛用例): 定义 设定(自): 自.ip_grabber = 我的课() 定义 曾夫人论坛_ip_grabber(自): ip = 自.ip_grabber.得到_ip() 自.assertIsInstance(ip, 基本串, “ 知识产权 应该是字符串”) 自.断言等于(ip.计数('。'), 3, “ 知识产权 应该有3个点”) 如果 __名称__ == '__主要__': 单元曾夫人论坛.主要() |
如您所见,这是一组标准曾夫人论坛,用于检查 ip_grabber 函数返回有效的IP地址。它运行如下:
1 2 3 4 5 6 |
脆弱的$ 蟒蛇 曾夫人论坛_my_module.py . ----------------------------------- 然 1 曾夫人论坛 在 0.293s 好 |
但是,这里的问题在于,每次运行曾夫人论坛时,它将调用实际的API。为了阻止这个,让’集成了模拟模块:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
进口 单元曾夫人论坛 进口 嘲笑 从 my_module 进口 我的课 类 fake_get(): 定义 __在里面__(自, 网址): 自.好 = 真正 定义 json(自): 返回 {'起源': '123'} 类 曾夫人论坛分类器(单元曾夫人论坛.曾夫人论坛用例): 定义 设定(自): 自.ip_grabber = 我的课() @嘲笑.补丁('my_module.get', 副作用=fake_get) 定义 曾夫人论坛_ip_grabber(自, fake_get): ip = 自.ip_grabber.得到_ip() 自.assertIsInstance(ip, 基本串, “ 知识产权 应该是字符串”) 自.断言等于(ip.计数('。'), 3, “ 知识产权 应该有3个点”) 如果 __名称__ == '__主要__': 单元曾夫人论坛.主要() |
这里 we’ve:
- 导入了模拟模块。注意:如果您收到有关“wraps” 在 the “six” module then it is almost certainly because you 有 more than 上e 在stallation of 六 要么 嘲笑 and 上e needs to be deleted.
- 创建一个假函数 fake_get替换 request.get 用。这实际上只是返回“123”现在,您可以在下面查看它如何使曾夫人论坛失败。
- 在test_ip_grabber函数周围添加了mock.patch包装器。这里非常重要的是指定函数名,因为它是在my_module中导入的,而不是在Python标准库中出现的;即我们正在做“my_module.get” rather than “requests.get”. The 副作用 = 然后说用我们想要的任何功能替换它。
- 现在必须将副作用指定的伪造函数添加为该函数的参数。
运行此,我们得到:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
脆弱的$ 蟒蛇 曾夫人论坛_my_module.py F ====================================================================== 失败: 曾夫人论坛_ip_grabber (__主要__.曾夫人论坛分类器) ----------------------------------- 追溯 (最 最近 呼叫 持续): 文件 “ /Library/Python/2.7/site-packages/mock/mock.py”, 线 1305, 在 修补 返回 功能(*args, **钥匙war) 文件 “ 曾夫人论坛_my_module.py”, 线 19, 在 曾夫人论坛_ip_grabber 自.断言等于(ip.计数('。'), 3, “ 知识产权 应该有3个点”) 断言错误: 知识产权 应该 有 3 点 ----------------------------------- 然 1 曾夫人论坛 在 0.002s 失败 (失败=1) |
嘲笑’s 副作用 已取代 request.get ðŸ™,要通过此操作,只需更换 返回 {'起源': '123'}与 返回 {'起源': '123.123.123.123'}再次运行:
1 2 3 4 5 6 |
脆弱的$ 蟒蛇 曾夫人论坛_my_module.py . ----------------------------------- 然 1 曾夫人论坛 在 0.000s 好 |
曾夫人论坛通过和零HTTP流量! ðŸ™,