【问题标题】:How to test Flask router methods with HTTPBasicAuth annotations如何使用 HTTP Basic Auth 注释测试 Flask 路由方法
【发布时间】:2018-07-09 14:41:27
【问题描述】:

我是 Python 新手,我尝试在 Flask 上实现 REST API 服务。我遇到了与我的代码测试相关的问题。我的 Flask 应用看起来像这样:

from flask import Flask, jsonify, make_response, request
from flask_httpauth import HTTPBasicAuth
import os

auth = HTTPBasicAuth()

@auth.get_password
def get_password(username):
    if username == os.environ['SERVICE_KEY']:
        return os.environ['SERVICE_PASS']
    return None

@auth.error_handler
def unauthorized():
    return make_response(jsonify({'error': 'Unauthorized access'}), 403)

app = Flask(__name__)

tweets = [
    {
        'id': 1,
        'profileId': '1',
        'message': 'My test tweet'
    },
    {
        'id': 2,
        'profileId': '1',
        'message': 'Second tweet!'
    }
]

@app.route('/api/v1/tweets', methods=['GET'])
@auth.login_required
def get_tweets():
    return jsonify({'tweets': tweets}), 200

@app.errorhandler(404)
@auth.login_required
def not_found(error):
    return make_response(jsonify({'error': 'Not found'}), 404)

if __name__ == '__main__':
    app.run(debug=True)

这是我的测试(目前仅适用于not_found 方法):

import unittest
from app import app

class TestApp(unittest.TestCase):

    def setUp(self):
        self.app = app.test_client()

    def test_404(self):
        rv = self.app.get('/i-am-not-found')
        self.assertEqual(rv.status_code, 404)


if __name__ == '__main__':
    unittest.main()

但是当我尝试运行测试时,由于收到“未经授权的访问”响应而失败:

>python test.py
F
======================================================================
FAIL: test_404 (__main__.TestApp)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "test.py", line 25, in test_404
    self.assertEqual(rv.status_code, 404)
AssertionError: 403 != 404

----------------------------------------------------------------------
Ran 1 test in 0.000s

FAILED (failures=1)

哪种测试路由方法的方法更适合处理授权?我该如何解决这个失败的测试?

【问题讨论】:

  • 为什么您的 404 错误处理程序中有 login_required?删除它,我认为你的测试会起作用!
  • 我同意你的观点,对于 404 错误处理程序 'login_required' 不是必需的,但是我将添加的其他路由处理程序呢,它们将使用 'login_required' 保护并且我想要测试?
  • 如果您发送必要的登录请求,那么这些处理程序应该可以正常工作。 Flask 测试客户端可以维护一个用户会话。
  • 谢谢@Miguel,我会看看的!

标签: python python-3.x testing flask python-unittest


【解决方案1】:

您需要创建一个包含您的身份验证详细信息的自定义标头,并将其与您的请求一起发送。像这样的:

from base64 import b64encode    
...
headers = {'Authorization': 'Basic ' + b64encode("{0}:{1}".format(username, password))}
rv = self.app.get('/i-am-not-found', headers=headers)
...


import unittest
from app import app

class TestApp(unittest.TestCase):

    def setUp(self):
        self.app = app.test_client()

    def test_404(self):
        headers = {
            'Authorization': 'Basic ' + b64encode("username:password")
        }
        rv = self.app.get('/i-am-not-found', headers=headers)
        self.assertEqual(rv.status_code, 404)


if __name__ == '__main__':
    unittest.main()

您的用户名和密码以username:password 的形式发送,但采用base64 编码。如果扩展它,有一些方法可以简化它,例如提取到一个函数中以始终传递标头和外部化用户名/密码以进行测试。

编辑:此外,我认为您应该在此处返回 401 代码。 401 通常在凭据不正确时使用,403 通常在您成功验证自己但无权访问资源时使用。一个非常简单的示例,登录到 Facebook,但被限制访问标记为私人的其他人的照片。

【讨论】:

    猜你喜欢
    • 2017-03-09
    • 1970-01-01
    • 2020-02-14
    • 1970-01-01
    • 2016-08-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多