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.environ
的 BytesIO
对象=].因此,如果您 运行 使用 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
。
免责声明:我创作了。 (为工作而写。)
当单元测试一个 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.environ
的 BytesIO
对象=].因此,如果您 运行 使用 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
。
免责声明:我创作了。 (为工作而写。)