[Solved]-How to generate a file upload (test) request with Django REST Framework's APIRequestFactory?


It’s alright now! Switching from APIRequestFactory to APIClient, I managed to have my test running.

My new test.py:

import os
import tempfile
from django.conf import settings
from django.core.files import File
from django.core.files.uploadedfile import SimpleUploadedFile
from django.urls import reverse
from rest_framework.test import APITestCase, APIClient
from django.contrib.auth.models import User

class UploadVideoTestCase(APITestCase):
    def setUp(self):
        settings.MEDIA_ROOT = tempfile.mkdtemp()

    def test_video_uploaded(self):
        """Video uploaded"""
        filename = 'vid'
        file = File(open('media/testfiles/vid.mp4', 'rb'))
        uploaded_file = SimpleUploadedFile(filename, file.read(),
        client = APIClient()
        user = User.objects.get(username='michel')
        url = reverse('file_upload:upload_view', kwargs={'filename': filename})
        client.put(url, {'file': uploaded_file}, format='multipart')
        dir_name = settings.MEDIA_ROOT + '/scene/' + filename + '/cam1'
        new_filename = 'orig.mp4'
        file_path = os.path.join(dir_name, new_filename)


Below, testing file upload using APIRequestFactory as requested (and ModelViewSet).

from rest_framework.test import APIRequestFactory, APITestCase
from my_project.api.views import MyViewSet
from io import BytesIO

class MyTestCase(APITestCase):

    def setUp(self):
        fd = BytesIO(b'Test File content')   # in-memory file to upload
        fd.seek(0)                           # not needed here, but to remember after writing to fd
        reqfactory = APIRequestFactory()     # initialize in setUp if used by more tests
        view = MyViewSet({'post': 'create'}) # for ViewSet {action:method} needed, for View, not.
        request = factory.post('/api/new_file/',
                "title": 'test file',
                "fits_file": self.fd,
            format='multipart')              # multipart is default, but for clarification that not json
        response = view(request)
        self.assertEqual(response.status_code, 201)

Note that there is no authorization for clarity, as with: 'DEFAULT_PERMISSION_CLASSES': ['rest_framework.permissions.AllowAny'].

Leave a comment