Ошибки контекста приложения при локальном тестировании (Python) облачной функции Google

Я пытаюсь локально протестировать функцию Python, которую надеюсь развернуть как облачную функцию Google. Эти функции, по-видимому, в основном основаны на Flask, и я обнаружил, что лучший способ вернуть JSON - использовать функцию Flask jsonify. Кажется, это работает нормально при развертывании, но я хочу настроить некоторые локальные модульные тесты, и вот где я застрял. Простое добавление строки для импорта jsonify приводит к следующей ошибке:

RuntimeError: Working outside of application context.

Здесь есть несколько сообщений в Stackru, которые, по-видимому, имеют отношение к этой проблеме, но облачные функции 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)

2 ответа

Решение

Я бы порекомендовал вам взглянуть на документацию Flask о том, как тестировать приложения Flask, там очень хорошо описано, как настроить тест и получить контекст приложения.

PS 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()