首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >酒瓶http-auth和单元测试

酒瓶http-auth和单元测试
EN

Stack Overflow用户
提问于 2015-01-16 11:39:53
回答 2查看 2.5K关注 0票数 6

嗨!

我有一个使用HTTPAuth实现的HTTP基本身份验证保护的路由。如果使用curl,一切都可以正常工作(我可以访问路由),但在单元测试时,即使我提供了正确的用户名和密码,也无法访问路由。

下面是测试模块中的相关代码片段:

代码语言:javascript
复制
class TestClient(object):
    def __init__(self, app):
        self.client = app.test_client()

    def send(self, url, method, data=None, headers={}):
        if data:
            data = json.dumps(data)

        rv = method(url, data=data, headers=headers)
        return rv, json.loads(rv.data.decode('utf-8'))

    def delete(self, url, headers={}):
        return self.send(url, self.client.delete, headers)

class TestCase(unittest.TestCase):
    def setUp(self):
        app.config.from_object('test_config')
        self.app = app
        self.app_context = self.app.app_context()
        self.app_context.push()
        db.create_all()
        self.client = TestClient(self.app)

    def test_delete_user(self):
        # create new user
        data = {'username': 'john', 'password': 'doe'}
        self.client.post('/users', data=data)

        # delete previously created user
        headers = {}
        headers['Authorization'] = 'Basic ' + b64encode((data['username'] + ':' + data['password'])
                                                        .encode('utf-8')).decode('utf-8')
        headers['Content-Type'] = 'application/json'
        headers['Accept'] = 'application/json'
        rv, json = self.client.delete('/users', headers=headers)
        self.assertTrue(rv.status_code == 200) # Returns 401 instead

以下是所需的回调方法:

代码语言:javascript
复制
auth = HTTPBasicAuth()

@auth.verify_password
def verify_password(username, password):
    # THIS METHOD NEVER GETS CALLED
    user = User.query.filter_by(username=username).first()
    if not user or not user.verify_password(password):
        return False
    g.user = user
    return True

@auth.error_handler
def unauthorized():
    response = jsonify({'status': 401, 'error': 'unauthorized', 'message': 'Please authenticate to access this API.'})
    response.status_code = 401
    return response

任何我的路线:

代码语言:javascript
复制
@app.route('/users', methods=['DELETE'])
@auth.login_required
def delete_user():
    db.session.delete(g.user)
    db.session.commit()
    return jsonify({})

单元测试引发以下异常:

代码语言:javascript
复制
Traceback (most recent call last):
  File "test_api.py", line 89, in test_delete_user
    self.assertTrue(rv.status_code == 200) # Returns 401 instead
AssertionError: False is not true

我想再次强调,当我使用与我为测试客户端提供的完全相同的参数运行curl时,一切都很好,但是当我运行测试时,verify_password方法甚至都没有被调用。

非常感谢您的帮助!

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2015-01-16 19:38:36

你会喜欢这个的。

您的send方法:

代码语言:javascript
复制
def send(self, url, method, data=None, headers={}):
    pass

您的delete方法:

代码语言:javascript
复制
def delete(self, url, headers={}):
    return self.send(url, self.client.delete, headers)

注意,您将headers作为第三个位置参数传递,因此它将作为data传递到send()中。

票数 2
EN

Stack Overflow用户

发布于 2017-08-02 15:05:36

下面是一个如何使用pytest和内置的monkeypatch夹具来完成这一任务的例子。

如果我在some_flask_app中有这个API函数

代码语言:javascript
复制
from flask_httpauth import HTTPBasicAuth

app = Flask(__name__)
auth = HTTPBasicAuth()

@app.route('/api/v1/version')
@auth.login_required
def api_get_version():
    return jsonify({'version': get_version()})

我可以创建一个夹具,返回一个烧瓶测试客户端,并在HTTPBasicAuth中对身份验证函数进行修补,以始终返回True

代码语言:javascript
复制
import pytest
from some_flask_app import app, auth

@pytest.fixture(name='client')
def initialize_authorized_test_client(monkeypatch):
    app.testing = True
    client = app.test_client()
    monkeypatch.setattr(auth, 'authenticate', lambda x, y: True)
    yield client
    app.testing = False


def test_settings_tracking(client):
    r = client.get("/api/v1/version")
    assert r.status_code == 200
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/27983158

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档