首页 > 解决方案 > flask.request mocker.patch.object 不生效

问题描述

在我的控制器中,我得到了这个端点:

@bp_crawler.route('/insert', methods=['POST'])
def insert_data():
    req = requests.CrawledSocialDataRequest.from_json(json.loads(request.data))

pytest然后,我尝试用夹具测试pytest-mockmocker

我继续模拟该request对象,以便request.data返回一些对我的单元测试有用的值。

# arrange
data_to_insert = requests.CrawledSocialDataRequest([
    requests.CrawledSocialDataRecord('cid0', 'content0', 123.4, ['tag0', 'tag1']),
    requests.CrawledSocialDataRecord('cid1', 'content1', 123.4, ['tag1', 'tag2'])
])
request_mock = mocker.patch.object(flask, 'request')
request_mock.data = data_to_insert.serialize()

db_mock = request_mock = mocker.patch.object(api, 'db')

# act
result = controller.insert_data()

一切都很好,除了insert_data()被调用的时候。

我得到以下异常:

    controllers/v1/tests/test_crawler.py:30: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

    controllers/v1/crawler.py:36: in insert_data
        req = requests.CrawledSocialDataRequest.from_json(json.loads(request.data))
    /usr/local/lib/python3.7/site-packages/werkzeug/local.py:347: in __getattr__
        return getattr(self._get_current_object(), name)
    /usr/local/lib/python3.7/site-packages/werkzeug/local.py:306: in _get_current_object
        return self.__local()


name = 'request'

    def _lookup_req_object(name):
        top = _request_ctx_stack.top
        if top is None:
>           raise RuntimeError(_request_ctx_err_msg)
E           RuntimeError: Working outside of request context.
E           
E           This typically means that you attempted to use functionality that needed
E           an active HTTP request.  Consult the documentation on testing for
E           information about how to avoid this problem.

模拟没有发生,因此 request.data 将控制路由到flask.globals,让我的单元测试失败。

Github 链接:

标签: pythonunit-testingflaskmockingpytest

解决方案


事实证明,如果_test.py你这样做:

import flask
...
request_mock = mocker.patch.object(flask, 'request')

但是在您的控制器/端点上,您可以

from flask import request
...
x = request.data # this will break

所以,你必须这样做import flask -> x = flask.request.data才能工作,或者改变模拟技术。


推荐阅读