Deven Phillips
Deven Phillips

Reputation: 1139

Test a Flask view that requires specific configuration, data, and headers

There is a function decorated with before_request which processes authentication headers and sets properties on the request. I want to test the /status route, but I do not see how to mock the headers and the before_request function. The view also checks against the database, which requires configuration as well. How do I set all three of these pieces when testing?

@before_request
def process_auth_headers():
    # Process auth headers and set properties on "request" object

@app.route("/status")
def status():
    # Check "request" object properties for auth results
import unittest
import os
from ccbackendvsphere.api.v3 import app

class TestFlaskApp(unittest.TestCase):
    def setUp(self):
        app.config['TESTING'] = True
        app.config['WTF_CSRF_ENABLED'] = False
        app.confg['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///' + os.path.join(basedir, 'test.db')
        self.flask_app = app.test_client()

    def test_unauthenticated_status_request(self):
        rv = self.flask_app.get("/status")

Upvotes: 0

Views: 702

Answers (3)

Bob Jordan
Bob Jordan

Reputation: 3217

I've found I need to liberally use app.preprocess_request() to start many of my tests. Also assuming use of pytest + Flask-Webtest, found it useful to use it in my fixture as such:

@pytest.fixture(scope='function')
def testapp(app, db):
    """A flask-webtest TestApp for the functional tests."""
    app.preprocess_request()
    return TestApp(app, db=db) 

Upvotes: 0

Randy Syring
Randy Syring

Reputation: 2109

I wouldn't unit test this. I would functional test it by setting the headers when making the request. I prefer using Flask-Webtest instead of the built in test client.

from unittest import TestCase
from flask_webtest import TestApp
from main import app, db

class ExampleTest(TestCase):
    def setUp(self):
        self.app = app
        self.w = TestApp(self.app, db=db, use_session_scopes=True)

    def test(self):
        resp = self.w.get('/status', headers=...)
        assert resp.request.custom_auth_property == 'some value'

This code isn't tested but will hopefully put you in the right direction.

Upvotes: 1

davidism
davidism

Reputation: 127310

You don't mock before_request callbacks, especially since in this case you're testing that callback. If your request requires configuration, database data, specific headers, etc., then you set those up when you set up the test app before you create the test client request.

There are of course ways to make this more convenient, but it's the same thing you would do during normal operation.

You've already demonstrated that you know how to set configuration. app.config is available.

Create a test database and set the config to point at it. Then commit to the database like normal. Most Flask database extensions require an app context, so push a context first.

with app.app_context():
    # commit data

The test client's methods accepts many arguments for building a request, including a headers= argument. So make the request with the correct headers.

self.flask_app.get('/status', headers={'my_header': 'value'})

Upvotes: 1

Related Questions