Home > OS >  How to skip/block the before_request call in pytest for Python flask application?
How to skip/block the before_request call in pytest for Python flask application?

Time:09-23

I have a sample flask application as below

from flask import Flask

app = Flask(__name__)

@app.before_request()
def before_request():
   # Something
   if true
       return True
   else
       return False 

@app.route("/")
def index():
    return "Hello World!"

Also I have a pytest for this

@pytest.fixture
def client():
    tester = app.test_client()
    yield tester

def test_index():
   response = client.get('/')
   assert response.status_code == 200

I want to write the test cases for my application.

Whenever I try to test the index ie / or any endpoint it will goto before_request first that it was my application design

Is there a way to skip the before_request in pytest?

So that i can test my functionality whether its working properly or not.

CodePudding user response:

Solution 1

Ideally, you should put conditions inside before_request() on which cases it should be skipped, such as in the docs which is based on the presence of a key in session:

@app.before_request
def load_user():
    if "user_id" in session:
        g.user = db.session.get(session["user_id"])

If that is done, we can then try to patch those objects in the condition (in the example above is session) to control whether it would be skipped or not.

src.py

from flask import Flask, session

app = Flask(__name__)


@app.before_request
def before_request():
    if "user_id" in session:
        return None  # Let's say we will skip if user_id is present
    print("Before request")


@app.route("/")
def index():
    print("Within index")
    return "Hello World!"

test_src.py

import pytest

from src import app


@pytest.fixture
def client():
    tester = app.test_client()
    yield tester


def test_index_mock_before_request(client, mocker):
    mocker.patch("src.session", {"user_id": None})  # Patch session to include "user_id" so that the before_request would be skipped

    response = client.get('/')
    assert response.status_code == 200


def test_index(client):
    response = client.get('/')
    assert response.status_code == 200

Solution 2

If changing the before_request() is not an option, an alternative solution (not recommended but would work) is to remove the unwanted before_request functions registered in the Flask-app object via its before_request_funcs.

src.py

...
# Same as above, just replace the following lines

@app.before_request
def before_request():
    print("Before request")
...

test_src.py

...
# Same as above, just replace the following lines

def test_index_mock_before_request(client, mocker):
    mocker.patch.object(app, "before_request_funcs", {})  # Remove all registered before_request functions so that they wouldn't be run

    response = client.get('/')
    assert response.status_code == 200
...

Output

$ pytest -q -rP
..                                                                                            [100%]
============================================== PASSES ===============================================
__________________________________ test_index_mock_before_request ___________________________________
--------------------------------------- Captured stdout call ----------------------------------------
Within index
____________________________________________ test_index _____________________________________________
--------------------------------------- Captured stdout call ----------------------------------------
Before request
Within index
2 passed in 0.14s
  • As you can see, with the patches, the code within before_request() wasn't executed.
  • Related