how to unit test file upload in django

后端 未结 11 1036
感动是毒
感动是毒 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:31

    I used to do the same with open('some_file.txt') as fp: but then I needed images, videos and other real files in the repo and also I was testing a part of a Django core component that is well tested, so currently this is what I have been doing:

    from django.core.files.uploadedfile import SimpleUploadedFile
    
    def test_upload_video(self):
        video = SimpleUploadedFile("file.mp4", "file_content", content_type="video/mp4")
        self.client.post(reverse('app:some_view'), {'video': video})
        # some important assertions ...
    

    In Python 3.5+ you need to use bytes object instead of str. Change "file_content" to b"file_content"

    It's been working fine, SimpleUploadedFile creates an InMemoryFile that behaves like a regular upload and you can pick the name, content and content type.

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

    I do something like this for my own event related application but you should have more than enough code to get on with your own use case

    import tempfile, csv, os
    
    class UploadPaperTest(TestCase):
    
        def generate_file(self):
            try:
                myfile = open('test.csv', 'wb')
                wr = csv.writer(myfile)
                wr.writerow(('Paper ID','Paper Title', 'Authors'))
                wr.writerow(('1','Title1', 'Author1'))
                wr.writerow(('2','Title2', 'Author2'))
                wr.writerow(('3','Title3', 'Author3'))
            finally:
                myfile.close()
    
            return myfile
    
        def setUp(self):
            self.user = create_fuser()
            self.profile = ProfileFactory(user=self.user)
            self.event = EventFactory()
            self.client = Client()
            self.module = ModuleFactory()
            self.event_module = EventModule.objects.get_or_create(event=self.event,
                    module=self.module)[0]
            add_to_admin(self.event, self.user)
    
        def test_paper_upload(self):
            response = self.client.login(username=self.user.email, password='foz')
            self.assertTrue(response)
    
            myfile = self.generate_file()
            file_path = myfile.name
            f = open(file_path, "r")
    
            url = reverse('registration_upload_papers', args=[self.event.slug])
    
            # post wrong data type
            post_data = {'uploaded_file': i}
            response = self.client.post(url, post_data)
            self.assertContains(response, 'File type is not supported.')
    
            post_data['uploaded_file'] = f
            response = self.client.post(url, post_data)
    
            import_file = SubmissionImportFile.objects.all()[0]
            self.assertEqual(SubmissionImportFile.objects.all().count(), 1)
            #self.assertEqual(import_file.uploaded_file.name, 'files/registration/{0}'.format(file_path))
    
            os.remove(myfile.name)
            file_path = import_file.uploaded_file.path
            os.remove(file_path)
    
    0 讨论(0)
  • 2020-12-02 07:36
    from django.test import Client
    from requests import Response
    
    client = Client()
    with open(template_path, 'rb') as f:
        file = SimpleUploadedFile('Name of the django file', f.read())
        response: Response = client.post(url, format='multipart', data={'file': file})
    

    Hope this helps.

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

    I did something like that :

    from django.core.files.uploadedfile import SimpleUploadedFile
    from django.test import TestCase
    from django.core.urlresolvers import reverse
    from django.core.files import File
    from django.utils.six import BytesIO
    
    from .forms import UploadImageForm
    
    from PIL import Image
    from io import StringIO
    
    
    def create_image(storage, filename, size=(100, 100), image_mode='RGB', image_format='PNG'):
       """
       Generate a test image, returning the filename that it was saved as.
    
       If ``storage`` is ``None``, the BytesIO containing the image data
       will be passed instead.
       """
       data = BytesIO()
       Image.new(image_mode, size).save(data, image_format)
       data.seek(0)
       if not storage:
           return data
       image_file = ContentFile(data.read())
       return storage.save(filename, image_file)
    
    
    class UploadImageTests(TestCase):
       def setUp(self):
           super(UploadImageTests, self).setUp()
    
    
       def test_valid_form(self):
           '''
           valid post data should redirect
           The expected behavior is to show the image
           '''
           url = reverse('image')
           avatar = create_image(None, 'avatar.png')
           avatar_file = SimpleUploadedFile('front.png', avatar.getvalue())
           data = {'image': avatar_file}
           response = self.client.post(url, data, follow=True)
           image_src = response.context.get('image_src')
    
           self.assertEquals(response.status_code, 200)
           self.assertTrue(image_src)
           self.assertTemplateUsed('content_upload/result_image.html')
    

    create_image function will create image so you don't need to give static path of image.

    Note : You can update code as per you code. This code for Python 3.6.

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

    As mentioned in Django's official documentation:

    Submitting files is a special case. To POST a file, you need only provide the file field name as a key, and a file handle to the file you wish to upload as a value. For example:

    c = Client()
    with open('wishlist.doc') as fp:
        c.post('/customers/wishes/', {'name': 'fred', 'attachment': fp})
    

    More Information: How to check if the file is passed as an argument to some function?

    While testing, sometimes we want to make sure that the file is passed as an argument to some function.

    e.g.

    ...
    class AnyView(CreateView):
        ...
        def post(self, request, *args, **kwargs):
            attachment = request.FILES['attachment']
            # pass the file as an argument
            my_function(attachment)
            ...
    

    In tests, use Python's mock something like this:

    # Mock 'my_function' and then check the following:
    
    response = do_a_post_request()
    
    self.assertEqual(mock_my_function.call_count, 1)
    self.assertEqual(
        mock_my_function.call_args,
        call(response.wsgi_request.FILES['attachment']),
    )
    
    0 讨论(0)
  • 2020-12-02 07:41

    From Django docs on Client.post:

    Submitting files is a special case. To POST a file, you need only provide the file field name as a key, and a file handle to the file you wish to upload as a value. For example:

    c = Client()
    with open('wishlist.doc') as fp:
      c.post('/customers/wishes/', {'name': 'fred', 'attachment': fp})
    
    0 讨论(0)
提交回复
热议问题