I would like to write a unit test for a view on a Django REST Framework application. The test should upload a file using PUT, in essence equivalent to
http -a malkarouri PUT http://localhost:8000/data-packages/upload/ka @tmp/hello.py
The code I have written so far is
factory = APIRequestFactory()
request = factory.put( '/data-packages/upload/ka',
data,
content_type='application/octet-stream',
content_disposition="attachment; filename=data.dump")
force_authenticate(request, user)
view = PackageView.as_view()
response = view(request, "k.py")
which, obviously, does not upload a file. The specific error when running the test is 400:
{u'detail': u'Missing filename. Request should include a Content-Disposition header with a filename parameter.'}
Notably, I am using a request factory to test the view rather than a full client. That is what makes solutions such as the one in this question not work for me.
What is the correct way to set the content disposition header?
So you have two choices: let ModelViewSet and ModelSerializer handle the job and send the request using content-type=multipart/form-data; set the field in ModelSerializer as Base64ImageField (or) Base64FileField and tell your client to encode the file to Base64 and set the content-type=application/json.
As usual CSRF validation will only apply to any session authenticated views. This means CSRF validation will only occur if the client has been logged in by calling login() .
APIRequestFactory : This is similar to Django's RequestFactory . It allows you to create requests with any http method, which you can then pass on to any view method and compare responses. APIClient : similar to Django's Client . You can GET or POST a URL, and test responses.
from django.core.files.uploadedfile import SimpleUploadedFile
from django.test import TestCase
from rest_framework.test import APIClient
class MyTest(TestCase):
client_class = APIClient
def test_it(self):
file = SimpleUploadedFile("file.txt", b"abc", content_type="text/plain")
payload = {"file": file}
response = self.client.post("/some/api/path/", payload, format="multipart")
self.assertEqual(response.status_code, 201)
# If you do more calls in this method with the same file then seek to zero
file.seek(0)
Hi you need to use the SimpleUploadedFile wrapper for that :
from django.core.files.uploadedfile import SimpleUploadedFile
from django.core.files import File
data = File(open('path/bond-data.dump', 'rb'))
upload_file = SimpleUploadedFile('data.dump', data.read(),content_type='multipart/form-data')
request = factory.put( '/data-packages/upload/ka',
{'file':upload_file,other_params},
content_type='application/octet-stream',
content_disposition="attachment; filename=data.dump")
Ps : I am using APITestCase
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With