pytest-dev / pytest-flask

A set of pytest fixtures to test Flask applications

Home Page:http://pytest-flask.readthedocs.org/en/latest/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Middleware advice/documentation

danpalmer opened this issue · comments

I'm trying to use pytest-flask to test a flask server that has some WSGI middleware wrapping it, but it seems this isn't supported as an exception is raised from within pytest-flask:

    @pytest.fixture(autouse=True)
    def _monkeypatch_response_class(request, monkeypatch):
        """Set custom response class before test suite and restore the original
        after. Custom response has `json` property to easily test JSON responses::

            @app.route('/ping')
            def ping():
                return jsonify(ping='pong')

            def test_json(client):
                res = client.get(url_for('ping'))
                assert res.json == {'ping': 'pong'}

        """
        if 'app' not in request.fixturenames:
            return

        app = request.getfuncargvalue('app')
        monkeypatch.setattr(app, 'response_class',
>                           _make_test_response_class(app.response_class))
E       AttributeError: 'function' object has no attribute 'response_class'

This makes sense, as the flask app is no longer a flask app with all the properties that pytest-flask is expecting, but I'm unsure how to go about testing this as a result.

Is there a way to get around this with pytest-flask? Is there a different API I should be using for my middleware (or a different way of registering them) than WSGI middleware? Am I missing something obvious here?

Thanks for the help!

I just had the exact same error message after mistakenly returning the app function itself inside my app fixture, not the local app_ instance create from the create_app call.

@pjwerneck would you be able to provide a code snippet? I'm running into the same error.

Here's my conftest.py

import pytest

from server import server as flask_app


@pytest.fixture
def app():
    yield flask_app


@pytest.fixture
def client(app):
    return app.test_client()

@oneilk It was something like this

import pytest
from myapp import create_app

@pytest.fixture
def app():
    app_ = create_app()
    return app  # should be `return app_`

Hey @danpalmer, thanks for taking the time to open the issue.

This problem can probably be avoided by applying the wsgi middleware as suggested by the official flask docs as follows:

wsgi_app is the actual WSGI application. This is not implemented in __call__() so that Middlewares can be applied without losing a reference to the app object.

Instead of doing this:
app = MyMiddleware(app)

It’s a better idea to do this instead:
app.wsgi_app = MyMiddleware(app.wsgi_app)

I'll be closing this for now, feel free to reopen if the problem still persists (try including a minimal, reproducible example in this case).