如何在请求mock中模拟多个url



我有一个方法,它调用两个不同的端点并验证响应。

def foo_bar:
status_1 = requests.post(
"http://myapi/test/status1", {},
headers=headers)
status_2 = requests.post(
"http://myapi/test/status2", {},
headers=headers)

# and check the responses ...

我想在pytest中模拟两个url,如下所示:

def foo_test:
with requests_mock.Mocker() as m1:
m1.post('http://myapi/test/status1',
json={},
headers={'x-api-key': my_api_key})

m1.post('http://myapi/test/status2',
json={},
headers={'x-api-key': my_api_key})

它总是抛出错误

**NO mock address: http://myapi/test/status2**

它似乎只是嘲笑第一个url。

那么,有没有办法在一个方法中模拟多个url呢?

我认为你还有其他事情要做,一次模拟一个这样的路径是很正常的,这样你就可以简单地从不同的路径返回不同的值。你的例子适用于我:

import requests
import requests_mock
with requests_mock.Mocker() as m1:
my_api_key = 'key'
m1.post('http://myapi/test/status1',
json={},
headers={'x-api-key': my_api_key})
m1.post('http://myapi/test/status2',
json={},
headers={'x-api-key': my_api_key})
headers = {'a': 'b'}
status_1 = requests.post("http://myapi/test/status1", {}, headers=headers)
status_2 = requests.post("http://myapi/test/status2", {}, headers=headers)
assert status_1.status_code == 200
assert status_2.status_code == 200

是的。从文档中:"requests_mock.ANY中有一个特殊的符号,它充当通配符来匹配任何内容。它可以用作方法和/或URL的替换">

import requests_mock
with requests_mock.Mocker() as rm:
rm.post(requests_mock.ANY, text='resp')

我不确定这是否是最好的方法,但它对我有效。你可以在之后断言哪些URL被调用:

urls = [r._request.url, for r in rm._adapter.request_history]

是的,有办法!

您需要使用additional_matcher回调(请参阅文档(和requests_mock.ANY作为URL。

您的示例(使用上下文管理器(

import requests
import requests_mock

headers = {'key': 'val', 'another': 'header'}

def my_matcher(request):
url = request.url
mocked_urls = [
"http://myapi/test/status1",
"http://myapi/test/status2",
]
return url in mocked_urls  # True or False
# as Context manager
with requests_mock.Mocker() as m1:
m1.post(
requests_mock.ANY,  # Mock any URL before matching
additional_matcher=my_matcher,  # Mock only matched
json={},
headers=headers,
)
r = requests.post('http://myapi/test/status1')
print(f"{r.text} | {r.headers}")
r = requests.post('http://myapi/test/status2')
print(f"{r.text} | {r.headers}")
# r = requests.get('http://myapi/test/status3').text  # 'NoMockAddress' exception

适用于pytest

注意:使用别名导入requests_mock库(因为requests_mock是pytest测试中的固定项(
请参阅pytest框架、GET方法和URL的示例:

# test_some_module.py
import requests
import requests_mock as req_mock

def my_matcher(request):
url = request.url
mocked_urls = [
"http://myapi/test/status1",
"http://myapi/test/status2",
]
return url in mocked_urls  # True or False

def test_mocking_several_urls(requests_mock):  # 'requests_mock' is fixture here
requests_mock.get(
req_mock.ANY,  # Mock any URL before matching
additional_matcher=my_matcher,  # Mock only matched
text="Some fake response for all matched URLs",
)
... Do your requests ...
# GET URL#1 -> response "Some fake response for all matched URLs"
# GET URL#2 -> response "Some fake response for all matched URLs"
# GET URL#N -> Raised exception 'NoMockAddress' 

最新更新