how to unit test file upload in django

后端 未结 11 1037
感动是毒
感动是毒 2020-12-02 07:09

In my django app, I have a view which accomplishes file upload.The core snippet is like this

...
if  (request.method == \'POST\'):
    if request.FILES.has_         


        
相关标签:
11条回答
  • 2020-12-02 07:43
    from rest_framework.test import force_authenticate
    from rest_framework.test import APIRequestFactory
    
    factory = APIRequestFactory()
    user = User.objects.get(username='#####')
    view = <your_view_name>.as_view()
    with open('<file_name>.pdf', 'rb') as fp:
        request=factory.post('<url_path>',{'file_name':fp})
    force_authenticate(request, user)
    response = view(request)
    
    0 讨论(0)
  • 2020-12-02 07:50

    if you want to add other data with file upload then follow the below method

    file = open('path/to/file.txt', 'r', encoding='utf-8')

        data = {
            'file_name_to_receive_on_backend': file,
            'param1': 1,
            'param2': 2,
            .
            .
        }
    
        response = self.client.post("/url/to/view", data, format='multipart')`
    

    The only file_name_to_receive_on_backend will be received as a file other params received normally as post paramas.

    0 讨论(0)
  • 2020-12-02 07:53

    I recommend you to take a look at Django RequestFactory. It's the best way to mock data provided in the request.

    Said that, I found several flaws in your code.

    • "unit" testing means to test just one "unit" of functionality. So, if you want to test that view you'd be testing the view, and the file system, ergo, not really unit test. To make this point more clear. If you run that test, and the view works fine, but you don't have permissions to save that file, your test would fail because of that.
    • Other important thing is test speed. If you're doing something like TDD the speed of execution of your tests is really important. Accessing any I/O is not a good idea.

    So, I recommend you to refactor your view to use a function like:

    def upload_file_to_location(request, location=None): # Can use the default configured
    

    And do some mocking on that. You can use Python Mock.

    PS: You could also use Django Test Client But that would mean that you're adding another thing more to test, because that client make use of Sessions, middlewares, etc. Nothing similar to Unit Testing.

    0 讨论(0)
  • 2020-12-02 07:54

    In Django 1.7 there's an issue with the TestCase wich can be resolved by using open(filepath, 'rb') but when using the test client we have no control over it. I think it's probably best to ensure file.read() returns always bytes.

    source: https://code.djangoproject.com/ticket/23912, by KevinEtienne

    Without rb option, a TypeError is raised:

    TypeError: sequence item 4: expected bytes, bytearray, or an object with the buffer interface, str found
    
    0 讨论(0)
  • 2020-12-02 07:56

    I am using Python==3.8.2 , Django==3.0.4, djangorestframework==3.11.0

    I tried self.client.post but got a Resolver404 exception.

    Following worked for me:

    import requests
    upload_url='www.some.com/oaisjdoasjd' # your url to upload
    with open('/home/xyz/video1.webm', 'rb') as video_file:
        # if it was a text file we would perhaps do
        # file = video_file.read()
        response_upload = requests.put(
            upload_url,
            data=video_file,
            headers={'content-type': 'video/webm'}
        )
    
    0 讨论(0)
提交回复
热议问题