python - 如何将数据模拟为 request.Response python 中的类型

标签 python python-3.x pytest python-unittest python-unittest.mock

我想写一些测试用例来练习 isinstance(obj, requests.Response) 逻辑中的object_check。在我创建模拟数据作为 requests.post 的返回值之后。模拟数据的类型始终是 Mock 类。这样,我怎样才能重写模拟数据,使模拟数据可以成为请求类型。响应?这样我就可以练习行 d = obj.json()?

from unittest.mock import patch, Mock
import unittest
import requests
from requests.exceptions import HTTPError
import pytest
def object_check(obj):
    if isinstance(obj, bytes):
        d = ujson.decode(obj.decode())
    elif isinstance(obj, requests.Response):
        d = obj.json()
    else:
        raise ValueError('invalid type')
    return d

def service_post(params):
    """
    trivial function that does a GET request
    against google, checks the status of the
    result and returns the raw content
    """
    url = "https://www.iamdomain.com"
    params = {'number': 1234, 'user_id': 1, 'name': 'john'}
    resp = requests.post(url, data=params)
    return object_check(resp)

@patch.object(requests, 'post')
def test_service_post(mock_request_post):
    data = {'number': 0000, 'user_id': 0, 'name': 'john'}
    def res():
        r = Mock()
        r.status_code.return_value = 200
        r.json.return_value = data
        return r
    mock_request_post.return_value = res()
    assert data == service_post(data)

最佳答案

你可以这样做:

@patch.object(requests, 'post')
def test_service_post(mock_request_post):
    data = {'number': 0000, 'user_id': 0, 'name': 'john'}
    def res():
        r = requests.Response()
        r.status_code = 200
        def json_func():
            return data
        r.json = json_func
        return r
    mock_request_post.return_value = res()
    assert data == service_post(data)

当我在本地运行时,测试通过了。 请注意 Mock 是一种微气味。

我曾经是 Mock 的忠实粉丝。但是,随着我作为一名开发人员的成长,我真的会尽量避免它。它可能会诱使您进行一些非常糟糕的设计,并且它们可能真的很难维护(尤其是因为您正在修改 Mock 以保存返回值)。 Mock 还会产生一种虚假的安全感(即使 Web 服务发生巨大变化,您的测试仍会继续通过,因此您可能会在生产环境中爆炸)。我认为您在这里真的不需要它。两种选择:

  1. 您可以点击您尝试点击的任何服务,并使用 pickle 序列化(保存)该响应,然后存储到磁盘(将其保存在您的测试套件中)。然后让您的单元测试读回它并使用实际的响应对象。您仍然需要对 requests.post 进行修补,但至少返回值会为您排列好,您不必添加或修改它们您的需求/应用在增长。
  2. 刚刚上网。完全忘记 补丁:只需在测试中执行 POST 并检查响应。当然,这可能会很慢,并且只有在有互联网的情况下才能工作。而且你会遇到愚蠢的纯粹主义者,他们会告诉你永远不要在单元测试中这样做。如果您遇到其中一个纯粹的人,也许将其移至集成测试。但说真的,没有什么可以替代你在生产中实际要做的事情。这样做的好处是,如果 Web 服务发生变化,您会立即知道并修复您的代码。缺点是它会减慢您的测试套件的速度,并且它可能是一个不可靠的测试(如果 Web 服务关闭,您的测试将失败......但知道这一点实际上可能是件好事)。

如果网络服务不稳定(即容易更改),我建议使用选项 2。否则,使用选项 1。或者将两者结合使用(Mockpatch 进行单元测试,并在集成测试中点击服务)。只有你能决定!

HTH,祝你好运!

关于python - 如何将数据模拟为 request.Response python 中的类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51678972/

相关文章:

python-3.x - 在 16GB RAM 计算机上读取大型语言语料库,不会出现内存错误

python - 如何将特定于环境的应用程序配置传递给 Pytest

python - 如何使用 pytest 测试 Django 模型?

python 连接、映射和 lambda 方法

python - 适合数据点的角臂

python - Pandas:如何根据列表从数据框中删除行?

python - 需要帮助修改洪水填充算法

python - 如何在Python中解码这种奇怪的编码?

python - 如何用monkeypatch替换常量

python - flask 蓝图属性错误 : 'module' object has no attribute 'name' error