在本地测试 (Python) Google 云函数时出现应用程序上下文错误
Application context errors when locally testing a (Python) Google Cloud Function
我正在尝试在本地测试我希望部署为 Google 云函数的 Python 函数。这些函数似乎本质上是基于 Flask 的,我发现 return JSON 的最佳方法是使用 Flask 的 jsonify 函数。这在部署时似乎工作正常,但我想设置一些本地单元测试,这就是我卡住的地方。简单地添加行以导入 jsonify,会导致以下错误:
RuntimeError: Working outside of application context.
Whosebug 上有几篇帖子似乎与此问题相关,但 Google Cloud Functions 并未真正遵循 Flask 模式。据我所知,没有应用上下文,也没有装饰器。我发现的所有示例对这个特定用例都没有用处。任何人都可以建议一种构建单元测试的方法,该方法将尊重应用程序上下文并仍然与此处的 GCF 模式保持一致。
我有一个单元测试,我可以分享它,但是当你 运行 下面的方法调用在 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)
I'd recommend you to take a look at Flask's documentation on how to test Flask apps,它很好地描述了如何设置测试和获取应用程序上下文。
P.S。 jsonify
需要应用程序上下文,但 json.dumps
不需要。也许你可以使用后者?
您真的不需要测试 flask.jsonify
是否按预期工作,对吧?这是第三方功能。
您实际上要测试的是 flask.jsonify
是使用正确的数据调用的,因此您可以只修补 flask.jsonify
,并对模拟是否被调用做出断言:
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()
我遇到了同样的问题。正如您所说,烧瓶测试似乎不太适合 Cloud Functions,我对代码的工作方式很满意,所以不想改变它。在测试的 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()
我正在尝试在本地测试我希望部署为 Google 云函数的 Python 函数。这些函数似乎本质上是基于 Flask 的,我发现 return JSON 的最佳方法是使用 Flask 的 jsonify 函数。这在部署时似乎工作正常,但我想设置一些本地单元测试,这就是我卡住的地方。简单地添加行以导入 jsonify,会导致以下错误:
RuntimeError: Working outside of application context.
Whosebug 上有几篇帖子似乎与此问题相关,但 Google Cloud Functions 并未真正遵循 Flask 模式。据我所知,没有应用上下文,也没有装饰器。我发现的所有示例对这个特定用例都没有用处。任何人都可以建议一种构建单元测试的方法,该方法将尊重应用程序上下文并仍然与此处的 GCF 模式保持一致。
我有一个单元测试,我可以分享它,但是当你 运行 下面的方法调用在 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)
I'd recommend you to take a look at Flask's documentation on how to test Flask apps,它很好地描述了如何设置测试和获取应用程序上下文。
P.S。 jsonify
需要应用程序上下文,但 json.dumps
不需要。也许你可以使用后者?
您真的不需要测试 flask.jsonify
是否按预期工作,对吧?这是第三方功能。
您实际上要测试的是 flask.jsonify
是使用正确的数据调用的,因此您可以只修补 flask.jsonify
,并对模拟是否被调用做出断言:
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()
我遇到了同样的问题。正如您所说,烧瓶测试似乎不太适合 Cloud Functions,我对代码的工作方式很满意,所以不想改变它。在测试的 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()