python - 在单元测试中将 JSON 发布到 Flask 端点时出现错误请求

标签 python unit-testing google-app-engine flask flask-jwt

<分区>

我发现了很多关于人们试图将 JSON 发布到 Flask 应用程序的问题,但这些都不是我遇到的问题。

我有一个简单的 REST API,它是使用 Flask 和 Flask-JWT 构建的,它在浏览器中运行良好,但我的单元测试遇到了障碍。该应用程序是 App Engine 应用程序,可以在本地开发服务器和 App Engine 上正常运行。我正在使用 python -m unittest <module> 运行我的单元测试.

我有一个使用简单工厂创建的基本 Flask 应用程序:

def create_app(name=__name__, cfg):
    app = Flask(name)
    app.config.update(cfg)

    CORS(app)
    JWT(app, auth_handler, identity_handler)

    @app.route('/api/v1/ping', methods=['GET'])
    def handle_ping():
        return jsonify({'message': 'pong'})

    # other routes ...

在上面,JWT期待一个 authentication_handler ,我已经实现了:

def auth_handler(identity, secret):
    # validate identity and secret
    return User(...)

我的客户端是 Angular.js,因此我将 JSON 发布到此端点。这在浏览器或 curl 中都可以正常工作:

$ curl -H "content-type:application/json" -d '{"username":"jackripper@example.com","password":"crm114"}'   http://localhost:8080/api/v1/auth

给我一​​个200 OK以及响应中的访问 token 。

我的简单测试用例是这样的:

conf = {
     'DEBUG': False,
    'TESTING': True,
    'SECRET_KEY': 'MoveAlongTheresNothingToSeeHere',
    'JWT_AUTH_URL_RULE': '/api/v1/auth'
}

class FlaskRouteTests(unittest.TestCase):
    def setUp(self):
        api = factory.create_app(__name__, conf)
        self.app = api.test_client()

    def tearDown(self):
        pass

    def testRoute(self):
        # This test works just fine
        resp = self.app.get('/api/v1/ping')
        self.assertEqual(resp.status, "200 OK", "Status should be 200, was %s" % resp.status)

    def testAuth(self):
        # This test does not work
        resp = self.app.post('http://localhost:8080/api/v1/auth',
                         data="{'username': 'jackripper@example.com', 'password': 'crm114'}",
                         content_type='application/json', charset='UTF-8')
        self.assertEqual(resp.status, "200 OK", "Status should be 200, was %s" % resp.status)

普通老GET测试(testRoute())工作正常但testAuth()给我一个 400 Bad Request我不知道为什么。

如果我查看werkzeug environ在它向我的 Flask 应用程序发送请求之前,我看到了这个:

{
 'SERVER_PORT': '8080',
 'SERVER_PROTOCOL': 'HTTP/1.1',
 'SCRIPT_NAME': '',
 'wsgi.input': <_io.BytesIO object at 0x111fa8230>,
 'REQUEST_METHOD': 'POST',
 'HTTP_HOST': 'localhost:8080',
 'PATH_INFO': '/api/v1/auth',
 'wsgi.multithread': False,
 'QUERY_STRING': '',
 'HTTP_CONTENT_TYPE': 'application/json',
 'HTTP_CONTENT_LENGTH': '53',
 'CONTENT_LENGTH': '53',
 'wsgi.version': (1, 0),
 'SERVER_NAME': 'localhost',
 'wsgi.run_once': False,
 'wsgi.errors': <open file '<stderr>', mode 'w' at 0x10fd2d1e0>,
 'wsgi.multiprocess': False,
 'flask._preserve_context': False,
 'wsgi.url_scheme': 'http',
 'CONTENT_TYPE': u'application/json'
}

所以,内容类型设置正确,如果我阅读 wsgi.input 的内容( BytesIO.getvalue() ) 我看到 {'username': 'jackripper@example.com', 'password': 'crm114'}

请求似乎在某个地方失败了之前它甚至击中了我的auth_handler ,所以在 werkzeug 或 Flask 的某个地方。

  • werkzeug EnvironBuilder将数据解释为 str并将其转换为 BytesIO流 - 我不知道这是否符合预期。
  • 我试过将数据作为字符串发布:data="{'username': 'jackripper@example.com', 'password': 'password'}"并作为字典:data={'username': 'jackripper@example.com', 'password': 'password'} ,但似乎没有什么区别。

那么,我的问题: 如何使用 Flask.test_client() 将 JSON 发布到单元测试中的端点?我是否遗漏了一些明显的东西?

最佳答案

您没有发布有效的 JSON:

data="{'username': 'jackripper@example.com', 'password': 'crm114'}",

注意单引号。 JSON 使用 引号;以下是有效的 JSON:

data='{"username": "jackripper@example.com", "password": "crm114"}',

关于python - 在单元测试中将 JSON 发布到 Flask 端点时出现错误请求,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35159847/

相关文章:

java - 如何在 Google App Engine 中设置环境变量/应用程序 secret

php - Django 或 Drupal,我应该使用哪个最适合我的需要?

python - 从复杂对象覆盖 __init__

Python:使用 pandas 数据帧中的数据更新字典

objective-c - OCMock 不 stub NSBundle 方法

google-app-engine - 什么会导致 App Engine 请求中未跟踪时间的高度可变性?

python - 检测零膨胀和过度分散的计数数据中的异常值

scala - 将模拟 Actor 注入(inject) Spray 路线进行测试

unit-testing - 代码覆盖率工具 Visual Studio 2010 C++

java - 灵活环境中的 App Engine 服务?