2015-01-16 10 views
3

안녕하세요!플라스크 http-auth 및 unittesting

나는 Flask-HTTPAuth에 의해 구현 된 HTTP 기본 인증을 사용하여 보호 한 경로가 있습니다. 컬을 사용하면 모든 것이 잘 작동합니다 (단, 경로에 액세스 할 수 있습니다). 단, 유닛 테스트를 할 때 경로에 액세스 할 수 없습니다. 올바른 사용자 이름과 비밀번호를 제공하더라도 말입니다. 플라스크-HTTPAuth에 필요한

다음
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 

하는 콜백 메소드 :

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 

상관 없음 경로 :

@app.route('/users', methods=['DELETE']) 
@auth.login_required 
def delete_user(): 
    db.session.delete(g.user) 
    db.session.commit() 
    return jsonify({}) 
다음

내 테스트 모듈의 관련 코드 조각입니다

단위 테스트에서 다음 예외가 throw됩니다.

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 

필자는 테스트 클라이언트를 제공 할 때와 똑같은 인수를 곱슬 곱슬하게 실행할 때 모든 것이 올바르게 작동한다는 것을 다시 한번 강조하고 싶지만, 테스트를 실행할 때 verify_password 메서드는 호출되지 않습니다.

도움 주셔서 감사합니다.

+0

을 할 수 단위 테스트에서 던진 오류 메시지를 게시 하시겠습니까? –

+0

내가 말했듯이 Flask-HTTPAuth는 401 상태 코드와 함께 응답 객체를 반환하는 unauthorized()로 리디렉션합니다. 원래 질문에 오류 메시지를 추가했습니다. – abc

+0

사용자를 추가하는 'POST'요청이 실제로 작동했는지 확인 했습니까? 해당 요청은 인증에서 제외됩니까? – Miguel

답변

2

당신은 이것을 좋아할 것입니다.

귀하의 send 방법 :

def send(self, url, method, data=None, headers={}): 
    pass 

귀하의 delete 방법은 send()data으로 일어나고 있도록, 세 번째 위치 인수로 headers을 전달하는

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

참고.

0

pytest와 inbuilt monkeypatch fixture로 어떻게 수행 할 수 있는지 예가 있습니다.

내가 some_flask_app에서이 API 함수가있는 경우 : 내가 HTTPBasicAuth에 인증합니다 기능을 플라스크 테스트 클라이언트를 반환하고 패치 고정물을 만들 수 있습니다

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()}) 

항상 True으로 돌아 가기 :

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