python - 如何使用模拟测试服务响应?
问题描述
我有以下服务和发布请求:
import requests
class Attt():
def get_req(self):
pload = {'username': 'Olivia', 'password': '123'}
r = requests.post('https://httpbin.org/post', data=pload)
print(r.text)
print(r.content)
obj=Attt()
obj.get_req()
我想模拟该请求,以便创建所需的服务响应。我写了一个如下的测试:
import unittest
from unittest.mock import patch
from mock_tutorial.attt import Attt
import pandas as pd
class TestMockService(unittest.TestCase):
def test_mock(self):
fake_json = [{'test': "mock"}]
with patch('mock_tutorial.attt.requests.post') as mock_get:
mock_get.return_value.status_code = 200
mock_get.return_value.json.return_value = fake_json
obj = Attt()
response = obj.get_req()
print('response json', response.json())
self.assertEqual(response.status_code, 200)
self.assertEqual(response.json(), fake_json)
if __name__ == "__main__":
unittest.main()
但由于该get_req
方法不返回响应,断言失败:AttributeError: 'NoneType' object has no attribute 'json'
。如何修改断言以检查 get_req 方法的响应是否已被相应地模拟到 fake_json 变量?
解决方案
这是因为您没有从中返回任何东西,Attt.get_req
因此它返回了None
。所以在你的测试中,它就像调用None.json()
. 您应该返回请求的响应:
...
class Attt():
def get_req(self):
...
return r
...
同样如文档所述,您应该将代码包装在attt.py中,以便在导入时不会执行:
if __name__ == "__main__":
obj=Attt()
obj.get_req()
这似乎很好,因为这只是为了教程。但请注意,您已经可以使用一些库来模拟requests
模块,例如requests-mock。
更新
如果该方法不返回任何内容,那么我们所能做的就是向目标功能添加一个间谍。但请注意,这在现实中是没有意义的,因为我们正在监视的是一个模拟/修补的功能,即requests.post
. 这只会有利于学习目的,但实际上,最好不要添加测试,因为它根本不会增加任何价值。为此,我们可以使用pytest-mock:
模拟教程/attt.py
import requests
class Attt():
def get_req(self):
pload = {'username': 'Olivia', 'password': '123'}
r = requests.post('https://httpbin.org/post', data=pload)
print(r.text)
print(r.content)
test_attt.py
from unittest.mock import patch
from mock_tutorial import attt
from mock_tutorial.attt import Attt
import pytest
def test_mock(mocker): # Run <pip install pytest-mock>
fake_json = [{'test': "mock"}]
with patch('mock_tutorial.attt.requests.post') as mock_get:
mock_get.return_value.status_code = 200
mock_get.return_value.json.return_value = fake_json
post_spy = mocker.spy(attt.requests, "post")
obj = Attt()
response = obj.get_req()
assert post_spy.spy_return.status_code == 200
assert post_spy.spy_return.json() == fake_json
推荐阅读
- unix - 如何列出另一个目录的内容而不在其中?
- r - 删除具有少于 9 个唯一观察值的 ID
- java - 使用 import static org.junit.jupiter.api.Assertions.* 时,“assertEquals(boolean, Boolean) 类型不明确”;
- python - 有没有办法将条件仅放在循环中的列表中的最后一个输入上?
- indexing - 表格中的索引和部分匹配
- python - 如何使用 python 在 Spark 结构化流中转换数据帧?
- javascript - 如何在 Flask 中的服务器文件上保存 JavaScript 变量
- swift - 当我启动模拟器时,我的选择器视图上有一个问号
- c# - 自定义路径边框
- javascript - 使用 ajax .load(),我的脚本没有加载。但在页面刷新时显示