0

I'm trying to test my Django REST API for file uploading.

The catch is that my server tries to validate the file so that the file has a recognised file type. Currently only text-based filetypes are allowed, like: docs, pdf, txt.

I've tried using a temporary file and now I just tried to read a file from the disk then gave up.

Whenever I use a temporary file the server responds with:

    {
        "cover_letter": [
            "The submitted data was not a file. Check the encoding type on the form."
        ],
        "manuscript": [
            "The submitted data was not a file. Check the encoding type on the form."
        ]
    }

This is my test:

 def test_user_can_submit_a_paper(self):
     """
         Ensure that an user is able to upload a paper.

         This test is not working.. yet
     """
     tmp_file = open("__init__.py", "w")
     data = {
         "title": "paper",
         "authors": "me",
         "description": "ma detailed description",
         "manuscript": base64.b64encode(tmp_file.read()).decode(),
         "cover_letter": base64.b64encode(tmp_file.read()).decode()
     }
     tmp_file.close()


     response = self.client.post(self.papers_submitted, data=urlencode(MultiValueDict(data)), content_type='application/x-www-form-urlencoded',
                                 HTTP_AUTHORIZATION=self.authorization_header)
     print(response.data)
     self.assertEqual(response.status_code, status.HTTP_200_OK)

     del data["cover_letter"]
     response = self.client.post(self.papers_submitted, data=urlencode(MultiValueDict(data)), content_type='application/x-www-form-urlencoded',
                                 HTTP_AUTHORIZATION=self.authorization_header)
     print(response.data)
     self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)

I have successfully tested this endpoint via postman but I don't know how to do it in Python.

Denis Nutiu
  • 1,178
  • 15
  • 22

2 Answers2

1

If I understand what you are asking, you'd like to test your DRF endpoint with a file upload, using python. You should use RequestFactory, which simulates a request -- it will be more like using Postman.

This answer Django: simulate HTTP requests in shell has an example of using RequestFactory, and there are multiple answers here django RequestFactory file upload for specific solutions on how to include uploaded files with RequestFactory.

Mark Chackerian
  • 21,866
  • 6
  • 108
  • 99
0

I've managed to come up with a solution thanks to Mark's answer. Here's the code if anyone is interested:

def test_user_can_submit_a_paper(self):
    from api.journal import PaperListSubmitted
    from django.test.client import RequestFactory
    from django.core.files import temp as tempfile
    """
        Ensure that an user is able to upload a paper.
    """

    request_factory = RequestFactory()
    manuscript = tempfile.NamedTemporaryFile(suffix=".txt")
    cover_letter = tempfile.NamedTemporaryFile(suffix=".txt")
    manuscript.write(b"This is my stupid paper that required me to research writing this test for over 5h")
    cover_letter.write(b"This is my stupid paper that required me to research writing this test for over 5h")
    manuscript.seek(0)
    cover_letter.seek(0)

    post_data = {
        "title": "My post title",
        "description": "this is my paper description",
        "authors": "no authors",
        "manuscript": manuscript,
        "cover_letter": cover_letter
    }

    request = request_factory.post(self.papers_submitted, HTTP_AUTHORIZATION=self.authorization_header,
                                   data=post_data)

    response = PaperListSubmitted.as_view()(request)
    self.assertEqual(response.status_code, status.HTTP_200_OK)
Denis Nutiu
  • 1,178
  • 15
  • 22