Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unit testing when using request.body fails with KeyError: 'wsgi.input' #727

Closed
atcol opened this issue Mar 4, 2015 · 4 comments
Closed

Comments

@atcol
Copy link
Contributor

atcol commented Mar 4, 2015

When unit testing a bottle py route function:

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

The following exception is raised:

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'

The code will work if running as a server via bottle's run function, it's purely when I call it as a normal Python function e.g. in a unit test that the exception is raised.

Being able to unit test the individual route functions is very useful, but I'm a bit stumped on this one.

@eric-wieser
Copy link
Contributor

How about:

with open('my_sample_input.txt') as f:
    request.body = f
    blah("booooo!")

request.__getattr__ is threadlocal, so I'm assuming __setattr__ is as well.

@atcol
Copy link
Contributor Author

atcol commented Mar 5, 2015

Same result I'm afraid. Thank you for the suggestion though.

@atcol
Copy link
Contributor Author

atcol commented Mar 9, 2015

The referenced pull request demonstrates the way to get unit tests of routes that need the request body working. For the lazy/googlers, here's how to do it (referencing the route definition above):

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)
blah("hihihi")

Essentially, you have to fake the relevant request headers and provide a IO object that can be iterated over un the bottle request parsing.

@keredson
Copy link
Contributor

util that implements this faking: boddle

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants