如何从视图中删除“ @ oidc.login_required”以进行单元测试?

时间:2019-07-29 09:56:23

标签: unit-testing mocking pytest flask-oidc

我使用进行用户登录,使用进行测试。对于单元测试,我想“删除” @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'

1 个答案:

答案 0 :(得分:0)

首先通过pip安装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压印