如何使用pytest模拟请求?

53
我正在编写一些单元测试代码,我想要模拟在我的函数内部使用的requests模块。
import requests

def get_employee(id):
    resp = requests.get(f'{__BASE_URL}/employee/{id}')
    if resp.status_code == 404:
        return None

    return resp.json()

我已经尝试使用这段代码进行模拟:

def test_get_employee(mocker):
    get_request_mock = mocker.patch.object(get_employee, "resp")
    print(get_request_mock)
    get_request_mock.status_code = 200
    get_request_mock.json.return_value = {'name': 'awesome-mock'}
    resp = get_employee('random-id')
    assert resp == {'name': 'awesome-mock'}
如何使用 mocker 模拟请求?这是可能的吗?
2个回答

52
你可以使用requests-mock(PyPI)来进行操作,其中有一个fixture可以用于pytest的使用。
以你的示例为例:
from correct.package import __BASE_URL
from requests import HTTPError


def test_get_employee(requests_mock):
    test_id = 'random-id'
    requests_mock.get(f'{__BASE_URL}/employee/{test_id}', json= {'name': 'awesome-mock'})
    resp = get_employee('random-id')
    assert resp == {'name': 'awesome-mock'}

def test_absent_employee(requests_mock):
    test_id = 'does_not_exist'
    requests_mock.get(f'{__BASE_URL}/employee/{test_id}', status_code=404)
    with pytest.raises(HTTPError):
        resp = get_employee(test_id)

2
但是我该如何模拟函数 get_employee(id) 中的行 requests.get(f'{__BASE_URL}/employee/{id}') - user866364
能够返回404吗? - user866364
是的。只需将 status=404 作为 get 函数的参数添加即可。 - ndclt
正确的包是什么鬼?到处都找不到它。 - Zizzipupp
2
@Zizzipupp 我认为 from correct.package import __BASE_URL 是指你的项目包,其中包含了你尝试模拟的资源的基本URL。我猜它可能在配置模块中找到。 - Cuthbeorht

-9

这可能会有所帮助

from unittest import TestCase

import requests
import requests_mock


class TestHTTPRequest(TestCase):
    def test_context_manager(self):
        with requests_mock.Mocker() as mock_request:
            mock_request.get("http://123-fake-api.com", text="Hello!")
            response = requests.get("http://123-fake-api.com")

        assert response.text == "Hello!"

32
这个回答没有使用在问题中明确要求的 pytest - Carsten

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接