Skip to content

Accessing SQLAlchemy in pytest results in RuntimeError: Working outside of application context. #188

@imbue

Description

@imbue

When using a combination of flask, sqlalchemy, functions framework and pytest I get an RuntimeError: Working outside of application context. error as soon as the function attempts to hit the schema.py file. Running locally works like a charm, trouble starts when running as test.

To pinpoint the problem I removed the Merchant.query usage so the function does not hit the schema.py file at all, which did result in a non failing (succeeding) test.

What am I doing wrong, or am I looking in the wrong place here?

Error stacktrace

_____________________________________________ ERROR collecting main_test.py _____________________________________________
main_test.py:3: in <module>
    from main import render_widget
src/functions.py:3: in <module>
    from src.database.schema import Merchant
src/database/schema.py:10: in <module>
    app.config['SQLALCHEMY_DATABASE_URI'] = \
/usr/local/lib/python3.9/site-packages/werkzeug/local.py:278: in __get__
    obj = instance._get_current_object()
/usr/local/lib/python3.9/site-packages/werkzeug/local.py:407: in _get_current_object
    return self.__local()  # type: ignore
/usr/local/lib/python3.9/site-packages/flask/globals.py:47: in _find_app
    raise RuntimeError(_app_ctx_err_msg)
E   RuntimeError: Working outside of application context.
E
E   This typically means that you attempted to use functionality that needed
E   to interface with the current application object in some way. To solve
E   this, set up an application context with app.app_context().  See the
E   documentation for more information.
================================================ short test summary info ================================================
ERROR main_test.py - RuntimeError: Working outside of application context.

Function main.py

from src.database.schema import Merchant

@functions_framework.http
def render_widget(request):
    merchant = Merchant.query.filter_by(host=request.host).first()

     if not merchant:
        return make_response("Host not allowed", 403)

    # ...

    return response

Database specification schema.py

from flask import current_app as app
from flask_sqlalchemy import SQLAlchemy

from src.config import POSTGRES_HOST, POSTGRES_PASSWORD, POSTGRES_USER, POSTGRES_DATABASE, POSTGRES_PORT

app.config['SQLALCHEMY_DATABASE_URI'] = \
    f'postgresql://{POSTGRES_USER}:{POSTGRES_PASSWORD}@{POSTGRES_HOST}:{POSTGRES_PORT}/{POSTGRES_DATABASE}'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False

db = SQLAlchemy(app)

class Merchant(db.Model):
    id = db.Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
    host = db.Column(db.String(100), nullable=False)
    # ...

Test main_test.py

from flask import Request, current_app
from werkzeug.test import EnvironBuilder


def test_render_widget():
    with current_app.app_context():
        builder = EnvironBuilder(
            method='GET',
        )

        env = builder.get_environ()
        req = Request(env)

        from main import render_widget

        res = render_widget(request=req)

        assert res.status_code == 200
        assert res.headers['Content-Type'] == 'application/javascript'

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions