python - 如何模拟请求和响应?

我正在尝试使用 Pythons mock package模拟 Python 的 requests 模块。让我在以下场景中工作的基本调用是什么?

在我的views.py 中,我有一个函数可以进行各种requests.get() 调用,每次都有不同的响应

def myview(request):
  res1 = requests.get('aurl')
  res2 = request.get('burl')
  res3 = request.get('curl')

在我的测试类中,我想做这样的事情,但无法弄清楚确切的方法调用

第 1 步:

# Mock the requests module
# when mockedRequests.get('aurl') is called then return 'a response'
# when mockedRequests.get('burl') is called then return 'b response'
# when mockedRequests.get('curl') is called then return 'c response'

第 2 步:

调用我的观点

第三步:

验证响应包含'a response'、'b response'、'c response'

如何完成第 1 步(模拟请求模块)?

最佳答案

您可以这样做(您可以按原样运行此文件):

import requests
import unittest
from unittest import mock

# This is the class we want to test
class MyGreatClass:
    def fetch_json(self, url):
        response = requests.get(url)
        return response.json()

# This method will be used by the mock to replace requests.get
def mocked_requests_get(*args, **kwargs):
    class MockResponse:
        def __init__(self, json_data, status_code):
            self.json_data = json_data
            self.status_code = status_code

        def json(self):
            return self.json_data

    if args[0] == 'http://someurl.com/test.json':
        return MockResponse({"key1": "value1"}, 200)
    elif args[0] == 'http://someotherurl.com/anothertest.json':
        return MockResponse({"key2": "value2"}, 200)

    return MockResponse(None, 404)

# Our test case class
class MyGreatClassTestCase(unittest.TestCase):

    # We patch 'requests.get' with our own method. The mock object is passed in to our test case method.
    @mock.patch('requests.get', side_effect=mocked_requests_get)
    def test_fetch(self, mock_get):
        # Assert requests.get calls
        mgc = MyGreatClass()
        json_data = mgc.fetch_json('http://someurl.com/test.json')
        self.assertEqual(json_data, {"key1": "value1"})
        json_data = mgc.fetch_json('http://someotherurl.com/anothertest.json')
        self.assertEqual(json_data, {"key2": "value2"})
        json_data = mgc.fetch_json('http://nonexistenturl.com/cantfindme.json')
        self.assertIsNone(json_data)

        # We can even assert that our mocked method was called with the right parameters
        self.assertIn(mock.call('http://someurl.com/test.json'), mock_get.call_args_list)
        self.assertIn(mock.call('http://someotherurl.com/anothertest.json'), mock_get.call_args_list)

        self.assertEqual(len(mock_get.call_args_list), 3)

if __name__ == '__main__':
    unittest.main()

重要提示:如果您的 MyGreatClass 类位于不同的包中,例如 my.great.package,您必须模拟 my.great.package.requests.get 而不仅仅是“request.get”。在这种情况下,您的测试用例将如下所示:

import unittest
from unittest import mock
from my.great.package import MyGreatClass

# This method will be used by the mock to replace requests.get
def mocked_requests_get(*args, **kwargs):
    # Same as above


class MyGreatClassTestCase(unittest.TestCase):

    # Now we must patch 'my.great.package.requests.get'
    @mock.patch('my.great.package.requests.get', side_effect=mocked_requests_get)
    def test_fetch(self, mock_get):
        # Same as above

if __name__ == '__main__':
    unittest.main()

享受吧!

https://stackoverflow.com/questions/15753390/

相关文章:

mysql - 重命名 MySQL 数据库

python - `sorted(list)` 与 `list.sort()` 有什么区别?

python - 在 Python 中使用 "continue"语句的示例?

python - 如何在 Python 中创建不可变对象(immutable对象)?

linux - bash中带有变量的别名

linux - 如何获取终端的字符编码

python - Django 数据库设置 'Improperly Configured' 错误

linux - 如何将第三列打印到最后一列?

linux - 如何从容器本身获取 Docker Linux 容器信息?

linux - Linux 的虚拟串行端口