本地测试(Python)Google Cloud函数时出现应用程序上下文错误

本地测试(Python)Google Cloud函数时出现应用程序上下文错误,python,flask,google-cloud-platform,google-cloud-functions,google-contacts-api,Python,Flask,Google Cloud Platform,Google Cloud Functions,Google Contacts Api,我正在尝试本地测试一个Python函数,希望将其部署为Google云函数。这些函数基本上都是基于Flask的,我发现返回JSON的最好方法是使用Flask的jsonify函数。这在部署时似乎工作得很好,但我想设置一些本地单元测试,这就是我遇到的问题。只需添加要导入jsonify的行,就会导致以下错误: RuntimeError: Working outside of application context. 这里有几篇关于Stackoverflow的文章似乎与这个问题有关,但Google云功能

我正在尝试本地测试一个Python函数,希望将其部署为Google云函数。这些函数基本上都是基于Flask的,我发现返回JSON的最好方法是使用Flask的jsonify函数。这在部署时似乎工作得很好,但我想设置一些本地单元测试,这就是我遇到的问题。只需添加要导入jsonify的行,就会导致以下错误:

RuntimeError: Working outside of application context.
这里有几篇关于Stackoverflow的文章似乎与这个问题有关,但Google云功能并没有真正遵循Flask模式。据我所知,没有应用程序上下文,也没有装饰程序。我发现的所有示例对于这个特定用例都没有用处。有人能推荐一种方法来构建一个单元测试,它将尊重应用程序上下文,并且仍然与这里的GCF模式相一致

我有一个unittest,我可以与大家分享,但是当您运行以下命令时,您会看到相同的错误,方法调用在main

import os
import json
from flask import jsonify
from unittest.mock import Mock

def dummy_request(request):

    request_json = request.get_json()
    if request_json and 'document' in request_json:
        document = request_json['document']
    else:
        raise ValueError("JSON is invalid, or missing a 'docuemnt' property")

    data = document
    return jsonify(data)


if __name__ == '__main__':
    data = {"document":"This is a test document"}
    request = Mock(get_json=Mock(return_value=data), args=data)
    result = dummy_request(request)
    print(result)
,它很好地描述了如何设置测试和获取应用程序上下文


p.S.
jsonify
需要应用程序上下文,但
json.dumps
不需要。也许您可以使用后者?

您实际上不需要测试flask.jsonify是否按预期工作,对吗?这是第三方功能

您实际要测试的是,
flask.jsonify
是使用正确的数据调用的,因此您可以只修补
flask.jsonify
,并断言是否调用了mock:

import flask
from unittest.mock import Mock, patch

def dummy_request(request):

    request_json = request.get_json()
    if request_json and 'document' in request_json:
        document = request_json['document']
    else:
        raise ValueError("JSON is invalid, or missing a 'docuemnt' property")

    data = document
    return flask.jsonify(data)


@patch('flask.jsonify')
def test(mock_jsonify):
    data = {"document": "This is a test document"}
    request = Mock(get_json=Mock(return_value=data), args=data)
    dummy_request(request)
    mock_jsonify.assert_called_once_with("This is a test document")


if __name__ == '__main__':
    test()

我遇到了同样的问题。正如您所说的,flask测试似乎不适合云函数,我对代码的工作方式很满意,所以不想改变这一点。在测试的setUp()中添加一个应用程序上下文,然后将其用于所需的调用对我来说很有效。像这样的

import unittest
import main
from flask import Flask

class TestSomething(unittest.TestCase):

    def setUp(self):
        self.app = Flask(__name__)

    def test_something(self):      

        with self.app.app_context():
            (body, code) = main.request_something()

        self.assertEqual(200, code, "The request did not return a successful response")

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

是的,我查看了文档,并能够编写一个简单的工作示例来测试Flask应用程序。然而,谷歌云功能并不是一个真正的烧瓶应用程序。它没有装饰器,其方法必须接收请求对象。所以,这条路线并没有真正起作用。目前,最好的选择似乎是按照您的建议,使用json.dumps返回json。我不再确定我是从哪里学到jsonify的想法的——可能是在Stackoverflow的其他地方。谢谢。这与pytest和上面的示例一起工作。当我将测试函数从Flask函数移到tests.py中时,仍然存在一些上下文错误。不过,我仍在努力。我不确定我是否理解,但请随意提出一个新问题,我很乐意看一看。我开始走这条路,因为我认为我需要Flask jsonify或Response方法来为Google Cloud函数生成正确的输出。我更习惯于AWS Lambda,其中有一个JSON格式的文件代理,每个函数都必须生成该格式。我已经意识到我可以简单地返回一个JSON字符串。至于头和状态代码,它们可以作为元组的一部分返回,如文档中所示:return('Hello World!',200,headers),因此,对我来说,最简单的选择是从函数中删除所有Flask响应内容,并正常测试。