Django tests - patch object in all tests

后端 未结 3 1354
不知归路
不知归路 2020-12-17 07:49

I need to create some kind of MockMixin for my tests. It should include mocks for everything that calls external sources. For example, each time I save model in

3条回答
  •  佛祖请我去吃肉
    2020-12-17 08:26

    I ended up creating a test runner to serve my purpose. I needed to mock the file storage so that images do not actually write to the file system while testing. The images object is being called in many tests thus patching each class would not be DRY. Also, I noticed that mocking the file itself would leave it on the system in case the test failed. But this method didn't.

    I created a file runner.py in the project root

    # runner.py
    from unittest.mock import patch
    
    from django.test.runner import DiscoverRunner
    
    from myapp.factories import ImageFactory
    
    
    class UnitTestRunner(DiscoverRunner):
    
        @patch('django.core.files.storage.FileSystemStorage.save')
        def run_tests(self, test_labels, mock_save, extra_tests=None, **kwargs):
            mock_save.return_value = ImageFactory.get_image()
            return super().run_tests(test_labels, extra_tests=None, **kwargs)
    

    Then I would run my tests using python manage.py tests --testrunner=runner.UnitTestRunner


    Just for clarity the ImageFactory.get_image method is a custom method

    from django.core.files.base import ContentFile
    from factory.django import DjangoModelFactory
    from io import BytesIO
    from PIL import Image as PilImage
    from random import randint
    
    class ImageFactory(DjangoModelFactory):
    
        @classmethod
        def get_image(cls, name='trial', extension='png', size=None):
            if size is None:
                width = randint(20, 1000)
                height = randint(20, 1000)
                size = (width, height)
    
            color = (256, 0, 0)
    
            file_obj = BytesIO()
            image = PilImage.new("RGBA", size=size, color=color)
            image.save(file_obj, extension)
            file_obj.seek(0)
            return ContentFile(file_obj.read(), f'{name}.{extension}')
    

提交回复
热议问题