首页 > 解决方案 > test_request_context 中的 Cating 烧瓶中止状态代码

问题描述

我想了解如何在仅对调用方法的测试中使用HTTPException引发的方法。flask.aborttest_request_context

# example.py
import flask

@api.route('/', methods=['POST'])
def do_stuff():
    param_a = get_param()
    return jsonify(a=param_a)

# check if request is json, return http error codes otherwise
def get_param():
    if flask.request.is_json():
        try:
           data = flask.request.get_json()
           a = data('param_a')
        except(ValueError):
            abort(400)
    else:
        abort(405)


# test_example.py
from app import app  # where app = Flask(__name__)
from example import get_param
import flask

def test_get_param(app):
    with app.test_request_context('/', data=flask.json.dumps(good_json), content_type='application/json'):
        assert a == get_param()

在上面的get_param方法中,我尝试abort如果失败is_json()get_json()失败。为了测试这一点,我test_request_context没有通过content_type,并且基于这个博客和这个答案,我尝试添加一个嵌套的上下文管理器,如下所示:

# test_example.py
from app import app  # where app = Flask(__name__)
from example import get_param
from werkzeug.exceptions import HTTPException
import flask

def test_get_param_aborts(app):
    with app.test_request_context('/', data=flask.json.dumps('http://example', 'nope'), content_type=''):
        with pytest.raises(HTTPException) as httperror:
            get_param()
            assert 405 == httperror

但我得到一个assert 405 == <ExceptionInfo for raises contextmanager>断言错误。

有人可以解释一下并建议一种方法来测试abort这种get_param方法吗?

更新: 根据@tmt 的回答,我修改了测试。然而,即使测试通过了,在调试时我注意到这两个断言从未达到!

# test_example.py
from app import app  # where app = Flask(__name__)
from example import get_param
from werkzeug.exceptions import HTTPException
import flask

def test_get_param_aborts(app):
    with app.test_request_context('/', data=flask.json.dumps('http://example', 'nope'), content_type=''):
        with pytest.raises(HTTPException) as httperror:
            get_param()  # <-- this line is reached
            assert 405 == httperror.value.code
            assert 1 ==2

标签: python-3.xflaskpytest

解决方案


httperrorExceptionInfo的一个实例,它是 pytest 自己的描述异常的类。一旦发生,httperror还将包含value属性,该属性将是HTTPException自身的实例。如果我的记忆是正确的HTTPException包含code等于 HTTP 状态代码的属性,那么您可以使用它来进行断言:

# test_example.py
from app import app
from example import get_param
from werkzeug.exceptions import HTTPException
import flask

def test_get_param_aborts(app):
    with app.test_request_context('/', data=flask.json.dumps(), content_type=''):
        with pytest.raises(HTTPException) as httperror:
            get_param()

        assert 405 == httperror.value.code

备注

  • get_param()需要在pytest.raises()上下文管理器中调用。
  • 断言需要在上下文管理器之外完成,因为一旦引发异常,上下文就会结束。
  • 我不知道pytest.raise你的错字是否真的存在于旧版本的 pytest 中。AFAIK 它应该是pytest.raises

推荐阅读