如何 skip/block before_request 在 pytest 中调用 Python flask 应用程序?

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

我有一个示例烧瓶应用程序如下

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!"

我也有一个 pytest

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

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

我想为我的应用程序编写测试用例。

每当我尝试测试索引 ie / 或任何端点时,它都会首先转到 before_request 这是我的应用程序设计

有没有办法在 pytest 中跳过 before_request?

这样我就可以测试我的功能是否正常工作。

解决方案 1

理想情况下,您应该将条件放在 before_request() 中,在哪些情况下应该跳过它,例如在 docs 中,它基于会话中是否存在密钥:

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

如果完成了,我们就可以尝试修补条件中的那些对象(在上面的例子中是session)来控制它是否会被跳过。

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

解决方案 2

如果更改 before_request() 不是一个选项,另一种解决方案(不推荐 但可行)是删除不需要的 before_request 注册函数在 Flask-app 对象中通过其 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
...

输出

$ 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
  • 如您所见,使用补丁后,before_request() 中的代码未被执行。