Search code examples
python-3.xunit-testingtornado

How to create a tornado unit test with file upload?


I am trying to create a unit test where I need to upload a CSV file. Here is a snippet I am trying to do,

from tornado.testing import AsyncHTTPTestCase
import json


class TestCSV(AsyncHTTPTestCase):
                                          
      def test_post_with_duplicates_csv_returns_400(self, *args, **kwargs):
          dup_file = open("test.csv", 'r')                
          body = {'upload': dup_file.read()}

          request_config = {                                                                                    
              'method': 'POST',                                                                                 
              'headers': {                                                                                      
                  'Content-Type': 'application/json',                            
                  'Origin': 'localhost'                                                                         
              },                                                                                                
              'body': json.dumps(payload)                                                                                                                                                        
          }                                                                                                                            

          response = self.fetch('http://localhost/file_upload', **request_config)                          
          self.assertEqual(response.code, 400)   

and the actual code looks for the uploaded file like this,

...
file = self.request.files['upload'][0]
...

This returns 500 status code with the following message,

HTTPServerRequest(protocol='http', host='127.0.0.1:46243', method='POST', uri='/v2/files/merchants/MWBVGS/product_stock_behaviors', version='HTTP/1.1', remote_ip='127.0.0.1')
    Traceback (most recent call last):
      File "/usr/local/lib/python3.6/site-packages/tornado/web.py", line 1699, in _execute
        result = await result
      File "/usr/local/lib/python3.6/site-packages/tornado/gen.py", line 191, in wrapper
        result = func(*args, **kwargs)
      File "/usr/app/src/handlers/merchants.py", line 463, in post
        file = self.request.files['upload'][0]
    KeyError: 'upload'

Can some one help me on why the file is not getting detected?

Env: Python 3.6, tornado


Solution

  • You're encoding the file as JSON, but the request.files fields are used for HTML multipart uploads. You need to decide which format you want to use (in addition to those formats, you can often just upload the file as the HTTP PUT body directly) and use the same format in the code and the test.

    Tornado doesn't currently provide any tools for producing multipart uploads, but the python standard library's email.mime package does.