Unit testing bottle py application that uses request body results in KeyError: 'wsgi.input'

Unit testing bottle py application that uses request body results in KeyError: 'wsgi.input'

当单元测试一个 bottle py 路由函数时:

from bottle import request, run, post
@post("/blah/<boo>")
def blah(boo):
    body = request.body.readline()
    return "body is %s" % body
blah("booooo!")

引发了以下异常:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 3, in blah
  File "bottle.py", line 1197, in body
    self._body.seek(0)
  File "bottle.py", line 166, in __get__
    if key not in storage: storage[key] = self.getter(obj)
  File "bottle.py", line 1164, in _body
    read_func = self.environ['wsgi.input'].read
KeyError: 'wsgi.input'

如果 运行 通过 bottle 的 run 函数作为服务器,代码将起作用,这纯粹是当我将其作为普通 Python 函数调用时,例如在单元测试中。

我错过了什么?我如何在单元测试中将其作为普通 python 函数调用?

我终于弄明白问题出在哪里了。我需要 "fake" 瓶子的请求环境才能很好地播放:

from bottle import request, run, post, tob
from io import BytesIO
body = "abc"
request.environ['CONTENT_LENGTH'] = str(len(tob(body)))
request.environ['wsgi.input'] = BytesIO()
request.environ['wsgi.input'].write(tob(body))
request.environ['wsgi.input'].seek(0)
# Now call your route function and assert

另一个问题是 Bottle 使用线程局部变量,并在您第一次访问 [=14] 上的 body 属性 时读取您放入 request.environBytesIO 对象=].因此,如果您 运行 使用 post 数据进行多次测试,例如在 TestCase 中,当您在请求回调中阅读它时,它只会 return 它最初给出的值,而不是您更新后的值。

解决方案是在每次测试之前清除存储在请求对象上的所有值,因此在您的 setUp(self) 中,您可以这样做:

class MyTestCase(TestCase):
    def setUp():
        # Flush any cached values
        request.bind({})

查看 https://pypi.python.org/pypi/boddle。在你的测试中你可以这样做:

from bottle import request, run, post
from boddle import boddle
@post("/blah/<boo>")
def blah(boo):
    body = request.body.readline()
    return "body is %s" % body

with boddle(body='woot'):
    print blah("booooo!")

这将打印 body is woot

免责声明:我创作了。 (为工作而写。)