如何删除"@ oidc.login_required"从一个角度进行单元测试? [英] How can I remove "@oidc.login_required" for unit testing from a view?
本文介绍了如何删除"@ oidc.login_required"从一个角度进行单元测试?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!
问题描述
我使用flask-oidc 用于用户登录,并 pytest 进行测试.对于单元测试,我想删除" @oidc.require_login
.我该怎么办?
我尝试过的
flask-o的工作方式大致为:
from flask import Flask, url_for, redirect
from flask_oidc import OpenIDConnect
app = Flask(__name__)
app.config['OIDC_CLIENT_SECRETS'] = 'client_secrets.json'
# Contents:
# Create client_id and client_secret at https://console.developers.google.com/apis/credentials
# {
# "web": {
# "client_id": "123456789012-abc123hi09123.apps.googleusercontent.com",
# "client_secret": "ab123456789ABCDEFGHIJKLM",
# "redirect_uris": ["http://localhost:5000"],
# "auth_uri": "https://accounts.google.com/o/oauth2/auth",
# "token_uri": "https://accounts.google.com/o/oauth2/token",
# "userinfo_uri": "https://www.googleapis.com/oauth2/v3/userinfo"
# }
# }
app.config['SECRET_KEY'] = 'uq4aKjUvWXTPTIyfCz7mTtcG'
app.config['OIDC_ID_TOKEN_COOKIE_SECURE'] = False
app.config['OIDC_SCOPES'] = ["openid", "profile", "email"]
app.config['OIDC_CALLBACK_ROUTE'] = '/authorization-code/callback'
oidc = OpenIDConnect(app)
@app.route('/')
@oidc.require_login
def index():
return redirect(url_for('personalized'))
@app.route('/personalized')
@oidc.require_login
def personalized():
info = oidc.user_getinfo(['email', 'openid_id'])
return 'Hello, {} ({})'.format(info.get('email'), info.get('openid_id'))
@app.route('/hello')
@oidc.require_login
def constant():
return 'Hello'
if __name__ == '__main__':
app.run(port=5000)
然后我希望单元测试可以模拟@oidc.require_login
:
# core modules
from unittest import mock
# 3rd party modules
import pytest
# internal modules
import exampleapp
@pytest.fixture
def client():
app = exampleapp.app
client = app.test_client()
yield client
@mock.patch("flask_oidc.OpenIDConnect")
def test_private(mock_require_login, client):
rv = client.get('/hello')
assert rv.data == b'Hello'
解决方案
首先安装 blinker
通过点子.我不确定为什么,但这是必需的.
然后这对我有用:
# core modules
from unittest import mock
# 3rd party modules
import pytest
from flask import appcontext_pushed, g
# internal modules
import exampleapp
@pytest.fixture
def client():
app = exampleapp.app
app.testing = True
app.before_request_funcs[None] = []
def handler(sender, **kwargs):
g.oidc_id_token = 'foobar'
client = app.test_client()
with appcontext_pushed.connected_to(handler, app):
yield client
def test_private(client):
with mock.patch.object(
exampleapp.oidc, "validate_token", return_value=True
):
rv = client.get('/hello')
assert rv.data == b'Hello'
https://github.com/fedora-infra/elections >
I use flask-oidc for user login and pytest for testing. For unit testing, I would like to "remove" @oidc.require_login
. How can I do that?
What I tried
The way flask-o works is roughly:
from flask import Flask, url_for, redirect
from flask_oidc import OpenIDConnect
app = Flask(__name__)
app.config['OIDC_CLIENT_SECRETS'] = 'client_secrets.json'
# Contents:
# Create client_id and client_secret at https://console.developers.google.com/apis/credentials
# {
# "web": {
# "client_id": "123456789012-abc123hi09123.apps.googleusercontent.com",
# "client_secret": "ab123456789ABCDEFGHIJKLM",
# "redirect_uris": ["http://localhost:5000"],
# "auth_uri": "https://accounts.google.com/o/oauth2/auth",
# "token_uri": "https://accounts.google.com/o/oauth2/token",
# "userinfo_uri": "https://www.googleapis.com/oauth2/v3/userinfo"
# }
# }
app.config['SECRET_KEY'] = 'uq4aKjUvWXTPTIyfCz7mTtcG'
app.config['OIDC_ID_TOKEN_COOKIE_SECURE'] = False
app.config['OIDC_SCOPES'] = ["openid", "profile", "email"]
app.config['OIDC_CALLBACK_ROUTE'] = '/authorization-code/callback'
oidc = OpenIDConnect(app)
@app.route('/')
@oidc.require_login
def index():
return redirect(url_for('personalized'))
@app.route('/personalized')
@oidc.require_login
def personalized():
info = oidc.user_getinfo(['email', 'openid_id'])
return 'Hello, {} ({})'.format(info.get('email'), info.get('openid_id'))
@app.route('/hello')
@oidc.require_login
def constant():
return 'Hello'
if __name__ == '__main__':
app.run(port=5000)
Then I hoped the unit test could mock the @oidc.require_login
away:
# core modules
from unittest import mock
# 3rd party modules
import pytest
# internal modules
import exampleapp
@pytest.fixture
def client():
app = exampleapp.app
client = app.test_client()
yield client
@mock.patch("flask_oidc.OpenIDConnect")
def test_private(mock_require_login, client):
rv = client.get('/hello')
assert rv.data == b'Hello'
解决方案
First install blinker
via pip. I'm not sure why, but it is required.
Then this works for me:
# core modules
from unittest import mock
# 3rd party modules
import pytest
from flask import appcontext_pushed, g
# internal modules
import exampleapp
@pytest.fixture
def client():
app = exampleapp.app
app.testing = True
app.before_request_funcs[None] = []
def handler(sender, **kwargs):
g.oidc_id_token = 'foobar'
client = app.test_client()
with appcontext_pushed.connected_to(handler, app):
yield client
def test_private(client):
with mock.patch.object(
exampleapp.oidc, "validate_token", return_value=True
):
rv = client.get('/hello')
assert rv.data == b'Hello'
Inpsired by https://github.com/fedora-infra/elections
这篇关于如何删除"@ oidc.login_required"从一个角度进行单元测试?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!
查看全文