如何在烧瓶单元测试中上传文本文件?

时间:2019-02-28 07:51:08

标签: python flask file-upload

我正在尝试为我的文件上传表单编写测试。 该表格是Flask应用程序的一部分。 我正在使用鼻子2运行测试。

表单会上传一个json文件。服务器应该解析该文件并将其放入数据库中。当我用浏览器手动测试时,一切工作正常。

视图的相关部分如下所示:

def upload():
    form = UploadForm()
    if request.method == 'POST':
        if form.validate_on_submit():
            # error happens at this line
            exercise_graph = json.load(request.files['graph'])
            # ...

    return render_template('exercises/upload.html', form=form)

测试中的相关功能如下:

    def upload_exercise(self, name, description):
        filename = name + ".json"
        data={
            'name' : name,
            'description' : description,
            'graph': (BytesIO(b"{}"), filename)
            }

        class TestingRequest(Request):
            """A testing request to use that will return a
            TestingFileStorage to test the uploading."""
            @property
            def files(self):
                d = MultiDict()
                d['graph'] = TestingFileStorage(filename=filename)
                return d

        app.request_class = TestingRequest

        return self.app.post('/exercises/upload',
            content_type='multipart/form-data',
            data=data,
            follow_redirects=True)

我确实将此code用作测试功能的起点。我必须将StringIO更改为BytesIO,否则werkzeug会抱怨它期望使用字节对象。对于另一种上载二进制文件的表单,相同的测试过程也可以正常工作。

运行测试时,出现以下错误:

======================================================================
ERROR: test_exercise_upload_post (tests.test_exercises.ExercisesTests)
----------------------------------------------------------------------
Traceback (most recent call last):
  File ".../test_exercises.py", line 130, in test_exercise_upload_post
    response = self.upload_exercise('PushUps', 'Push up your body with your arms')
  File ".../test_exercises.py", line 90, in upload_exercise
    follow_redirects=True)
  File ".../python3.6/site-packages/werkzeug/test.py", line 840, in post
    return self.open(*args, **kw)
  File ".../python3.6/site-packages/flask/testing.py", line 200, in open
    follow_redirects=follow_redirects
  File ".../python3.6/site-packages/werkzeug/test.py", line 803, in open
    response = self.run_wsgi_app(environ, buffered=buffered)
  File ".../python3.6/site-packages/werkzeug/test.py", line 716, in run_wsgi_app
    rv = run_wsgi_app(self.application, environ, buffered=buffered)
  File ".../python3.6/site-packages/werkzeug/test.py", line 923, in run_wsgi_app
    app_rv = app(environ, start_response)
  File ".../python3.6/site-packages/flask/app.py", line 2309, in __call__
    return self.wsgi_app(environ, start_response)
  File ".../python3.6/site-packages/flask/app.py", line 2295, in wsgi_app
    response = self.handle_exception(e)
  File ".../python3.6/site-packages/flask/app.py", line 1741, in handle_exception
    reraise(exc_type, exc_value, tb)
  File ".../python3.6/site-packages/flask/_compat.py", line 35, in reraise
    raise value
  File ".../python3.6/site-packages/flask/app.py", line 2292, in wsgi_app
    response = self.full_dispatch_request()
  File ".../python3.6/site-packages/flask/app.py", line 1815, in full_dispatch_request
    rv = self.handle_user_exception(e)
  File ".../python3.6/site-packages/flask/app.py", line 1718, in handle_user_exception
    reraise(exc_type, exc_value, tb)
  File ".../python3.6/site-packages/flask/_compat.py", line 35, in reraise
    raise value
  File ".../python3.6/site-packages/flask/app.py", line 1813, in full_dispatch_request
    rv = self.dispatch_request()
  File ".../python3.6/site-packages/flask/app.py", line 1799, in dispatch_request
    return self.view_functions[rule.endpoint](**req.view_args)
  File ".../python3.6/site-packages/flask_login/utils.py", line 261, in decorated_view
    return func(*args, **kwargs)
  File ".../exercises/views.py", line 54, in upload
    exercise_graph = json.load(request.files['graph'])
  File ".../python3.6/json/__init__.py", line 299, in load
    parse_constant=parse_constant, object_pairs_hook=object_pairs_hook, **kw)
  File ".../python3.6/json/__init__.py", line 354, in loads
    return _default_decoder.decode(s)
  File ".../python3.6/json/decoder.py", line 339, in decode
    obj, end = self.raw_decode(s, idx=_w(s, 0).end())
  File ".../python3.6/json/decoder.py", line 357, in raw_decode
    raise JSONDecodeError("Expecting value", s, err.value) from None
json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)

----------------------------------------------------------------------

似乎TestingFileStorage对象可能为空? 我不确定是否了解该机制的真正作用。 我在BytesIO对象中指定的数据如何传输到TestingFileStorage?

还有其他可以尝试的方法吗?

任何帮助将不胜感激。

0 个答案:

没有答案