如何删除"@ oidc.login_required"从一个角度进行单元测试? [英] How can I remove "@oidc.login_required" for unit testing from a view?

查看:211
本文介绍了如何删除"@ oidc.login_required"从一个角度进行单元测试?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用用于用户登录,并进行测试.对于单元测试,我想删除" @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 for user login and 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆