5

やあ!

Flask-HTTPAuth によって実装されている HTTP 基本認証を使用して保護したルートがあります。curl を使用するとすべて正常に動作します (ルートにアクセスできます) が、単体テストの際に、正しいユーザー名とパスワードを指定しても、ルートにアクセスできません。

私のテストモジュールに関連するコードスニペットは次のとおりです。

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

Flask-HTTPAuth で必要なコールバック メソッドは次のとおりです。

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

単体テストで次の例外がスローされます。

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メソッドは呼び出されません。

ご助力ありがとうございます!

4

2 に答える 2

2

あなたはこれを気に入るはずです。

あなたのsend方法:

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

あなたのdelete方法:

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

headers3 番目の位置引数として渡していることに注意dataしてくださいsend()

于 2015-01-16T19:38:36.353 に答える