Home > Enterprise >  Upload an Excel File using Flask test client without mocking
Upload an Excel File using Flask test client without mocking

Time:07-27

View for my API:

@api.resource('/project/<string:val>/upload')
class UploadView(Resource):
    @classmethod
    @jwt_required
    def post(self, val):
        uploaded_file = request.files['file']
        file_name = secure_filename(uploaded_file.filename)
        file_path = os.path.join('data','files',filename)
        try:
            uploaded_file.save(file_path)
            status_code = 200
            response["result"] = "done"
        except Exception as e:
            print(e)
        return Response(response, status_code)

PyTest function having client, headers passed in as fixtures in functional scope used in the test class:

def test_upload_view(self, client, headers):
    file_path = rootdir   'file.xlsx'
    file = FileStorage(
            stream=io.BytesIO(open(file_path, "rb").read()),
            filename="uploadedFile.xlsx",
            content_type="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
       )
    url = "/v1/project/K6400/upload"
    response = client.post(
                url,
                headers=headers,
                data=dict(file=file),
                follow_redirects=True,
                content_type="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
               )
    assert response.status_code == 200

I have set up and teardown methods implemented properly which also closes the opened file to avoid errors. I am still getting a 400 error on the POST method. My API works properly on the UI and downloads the file, but on unit testing, it is failing. I understand request.files['file'] is a FileStorage object so I have tried to covert into BytesIO in the stream argument. Not sure what, I am doing wrong. Help would be really appreciated.

CodePudding user response:

try the following code:

def test_upload_view(self, client, headers):
    file_path = rootdir   'file.xlsx'
    with open(file_path, 'rb') as xlsxFile:
        fileBytes = ByteIO(xlsxFile.read())

    fileBytes.seek(0)

    url = "/v1/project/K6400/upload"
    response = client.post(
                url,
                headers=headers,
                data=dict(files=[(xlsxFile, myFile.xlsx)]),
                follow_redirects=True
               )
    assert response.status_code == 200

this will also handle multiple files in the same request. to read the files use:

request.files.to_dict(flat=False).get('files', None)

or remove the dict for single file

CodePudding user response:

I figured out the answer, I had to use BytesIO:

def test_upload_view(self, client, headers):
    file_path = rootdir   'file.xlsx'
    with open(file_path, "rb") as fp:
        url = "/v1/project/K6400/upload"
        response = client.post(
                url,
                headers=headers,
                data={'file': (io.BytesIO(fp.read()), file_path)},
                follow_redirects=True
               )
    assert response.status_code == 200
  • Related