如何 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()
中的代码未被执行。
我有一个示例烧瓶应用程序如下
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()
中的代码未被执行。