在您的代码中模拟出API调用

使用任何积极开发的(python)编码项目,您都可以’re和您的团队每周将进行数百次相同的曾夫人论坛。如果有’向那里的任何第三方资源发出HTTP请求,这可能会导致问题。 API调用可能是一种支出,过多地刮擦同一源可能会导致IP黑名单,并且这些调用可能会减慢整个曾夫人论坛过程的速度,从而给代码部署过程增加了额外的负担。

为了解决这个问题,我们可以使用Python’的模拟库。模拟对于创建伪函数调用,伪类和其他可以返回伪值的伪对象非常有用。在大多数情况下,进行曾夫人论坛时,您实际上实际上是在曾夫人论坛应用程序如何解析数据,而不是第三方服务的可靠性。 API’的响应通常是相同的。模拟可以让您模拟API’响应并解析其数据,而不必每次都真正拨打电话。

It’设置起来非常棘手,所以我想我会写一个教程。情况设置有几个组成部分,但我’我会尽量解释一下。让’s说有一个提供一些有用的API响应的服务。那里’是一个由肯尼斯·雷茨(Kenneth Reitz)设置的网站HTTPBin,用于曾夫人论坛HTTP库,我们将在这里使用它。签出: //httpbin.org/ip内容如下:

的JavaScript
1
2
3
{
  “起源”: “ 123.123.123.123”,
}

让’s说我们的程序想获取IP地址中的 起源 领域。对–一个毫无意义的程序,但这类似于您的许多情况’ll encounter.

这里’是一个完全过度设计的类,无法从此服务获取数据。在类中初始化时 __在里面__,它将创建一个指向HTTPBin的base_url变量。主要的处理程序功能是 得到_ip功能,只需抓住那个领域’的内容。首先拨打电话 api_call 使用 request.get 获取该HTTP数据。

my_module.py
蟒蛇
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 而是使用反直觉的命名“副作用”特征。这是曾夫人论坛模块的预模拟:

曾夫人论坛_my_module.py
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:

  1. 导入了模拟模块。注意:如果您收到有关“wraps” 在 the “six” module then it is almost certainly because you 有 more than 上e 在stallation of 六 要么 嘲笑 and 上e needs to be deleted.
  2. 创建一个假函数 fake_get替换 request.get 用。这实际上只是返回“123”现在,您可以在下面查看它如何使曾夫人论坛失败。
  3. 在test_ip_grabber函数周围添加了mock.patch包装器。这里非常重要的是指定函数名,因为它是在my_module中导入的,而不是在Python标准库中出现的;即我们正在做“my_module.get” rather than “requests.get”. The 副作用 = 然后说用我们想要的任何功能替换它。
  4. 现在必须将副作用指定的伪造函数添加为该函数的参数。

运行此,我们得到:

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流量! ðŸ™,

发表评论

你一定是 登录 发表评论。