如何在python中将数据模拟为request.Response类型 [英] How to mock data as request.Response type in python

查看:69
本文介绍了如何在python中将数据模拟为request.Response类型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想在 isinstance(obj, requests.Response) 逻辑中编写一些测试用例来练习 object_check.在我创建 Mock 数据作为 requests.post 的返回值之后.模拟数据的类型始终是 Mock 类.这样,我如何重写模拟数据,以便模拟数据可以是 requests.Response 类型?所以我可以练习 d = obj.json()?

I would like to write some testcase to exercise object_check in isinstance(obj, requests.Response) logic. After I create Mock data as return value for requests.post. The type for mock data is always be Mock class. In that way, how can I rewrite mock data so mock data can be type of requests.Response? so I can exercise line 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 是一种小气味.

Test then passed for me when I ran it locally. Be aware that Mock is a mini-smell.

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

I used to be a big fan of Mock. As I've grown as a dev, though, I really try to avoid it. It can trick you into some really bad design, and they can be really hard to maintain (especially since you're modifying your Mock to hold return values). Mock can also create a false sense of security (your test will continue to pass even if the web services changes dramatically, so you might explode in prod). I don't think you really need it here. Two alternatives:

  1. 您可以点击您想要点击的任何服务,并使用 pickle 序列化(保存)该响应,并存储到磁盘(将其保存在您的测试套件中).然后让您的单元测试读回它并使用实际的响应对象.您仍然需要对 requests.post 进行patch,但至少返回值会为您排好队,您不必像这样添加或修改它们您的需求/应用不断增长.
  2. 只需上网.完全忘记 patch:只需在测试中执行 POST 并检查响应.当然,这可能会很慢,并且只有在您有互联网时才有效.你会遇到愚蠢的纯粹主义者,他们会告诉你永远不要在单元测试中这样做.如果您遇到那些纯粹的人之一,也许可以将其转移到集成测试中.但说真的,没有什么可以替代你在生产中实际要做的事情.这样做的好处是,如果 Web 服务发生变化,那么您将立即知道它并可以修复您的代码.缺点是它会减慢您的测试套件的速度,并且它可能是一个不可靠的测试(如果网络服务关闭,您的测试将失败......但实际上知道这一点可能会很好).
  1. You could hit whatever service you're trying to hit, and serialize (save) that response out with pickle, and store to disk (save it in your test suite). Then have your unit test read it back in and use the actual response object. You'd still have to patch over requests.post, but at least the return values will be lined up for you and you won't have to add or modify them as your needs/application grows.
  2. Just hit the web. Forget the patch entirely: just do the POST in your test and check the response. Of course, this might be slow, and will only work if you have internet. And you'll get goofy purists who will tell you to never to do this in a unit test. Maybe move it to an integration test if you run into one of those puristy people. But seriously, there's no substitute for doing what you're actually going to do in prod. The upside to doing this is that if the web service changes, then you'll know about it right away and can fix your code. Downside is it can slow down your test suite, and it's a potentially unreliable test (if the webservice is down, your test will fail...but it might actually be good to know that).

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

I recommend if the webservice is unstable (i.e liable to change), use option 2. Else, use option 1. Or do some combination of both (Mock and patch for a unit test, and hit the service on an integration test). Only you can decide!

HTH,祝你好运!

这篇关于如何在python中将数据模拟为request.Response类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆